侧边栏壁纸
博主头像
人生短短几个秋

行动起来,活在当下

  • 累计撰写 45 篇文章
  • 累计创建 20 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

设计模式

人生短短几个秋
2025-01-23 / 0 评论 / 0 点赞 / 60 阅读 / 0 字

设计模式简介

设计模式(Design Patterns)是软件开发中解决常见问题的模板或蓝图。它们提供了一种经过验证的方法来应对特定类型的挑战,从而帮助开发者编写更清晰、可维护和高效的代码。

design_pattern.png

什么是设计模式?

设计模式是一种通用解决方案,它不是完成的算法实现,也不是可以直接转换为代码的设计细节,而是在描述一个在上下文中不断出现的问题以及该问题的解决方案的核心。通过使用设计模式,可以简化复杂系统的构建,并提高代码的重用性和灵活性。

设计模式的基本要素

每个设计模式都包含了以下几个基本要素:

  1. 模式名称(Pattern Name):一个助记符,用于简洁地描述设计模式。
  2. 问题(Problem):该模式所要解决的问题及其适用环境。
  3. 解决方案(Solution):解决问题的方案,包括建议的设计和相互作用的对象。
  4. 效果(Consequences):应用该模式后可能带来的结果和权衡,包括优点和缺点。
  5. 实例(Example):具体的应用示例,展示如何在实际项目中使用该模式。

设计模式七种原则

设计模式的七种原则通常被称为“SOLID原则”,是面向对象设计中的基本原则,能够帮助开发人员编写出更加灵活、可扩展、可维护的代码。这七个原则分别是:

  • 单一职责原则(Single Responsibility Principle,SRP):一个类只负责一个职责或一个功能。这个原则强调的是高内聚、低耦合,可以降低类的复杂度,提高代码的可读性、可维护性和可重用性。
  • 开闭原则(Open-Closed Principle,OCP):一个类的行为应该是可扩展的,但是不可修改。这个原则强调的是代码的可维护性和可扩展性,通过抽象化来避免修改已有代码的风险,从而降低软件维护的成本。
  • 里氏替换原则(Liskov Substitution Principle,LSP):子类应该可以替换其父类并且不会影响程序的正确性。这个原则强调的是面向对象的继承和多态特性,通过保证子类的行为和父类一致,从而提高代码的可维护性和可扩展性。
  • 接口隔离原则(Interface Segregation Principle,ISP):一个类不应该依赖它不需要的接口,即一个类对其它类的依赖应该建立在最小的接口上。这个原则强调的是接口设计的合理性,避免不必要的接口导致类之间的耦合性过高,从而提高代码的灵活性和可维护性。
  • 依赖倒置原则(Dependency Inversion Principle,DIP):依赖于抽象而不是依赖于具体实现。这个原则强调的是代码的可扩展性和可维护性,通过抽象化来减少组件之间的耦合性,从而使得代码更加灵活、易于维护和扩展。
  • 迪米特法则(Law of Demeter,LoD):也叫最少知识原则(Least Knowledge Principle,LKP),一个对象应当对其他对象有尽可能少的了解,不需要了解的内容尽量不要去了解。这个原则强调的是组件之间的松耦合,通过减少组件之间的依赖关系,提高代码的可维护性和可重用性。
  • 组合/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)尽量使用组合或聚合关系,而不是继承关系来达到代码复用的目的。这个原则强调的是通过组合和聚合的方式来实现代码复用,避免继承带来的一些问题,如父类和子类之间的强耦合性,从而提高代码的灵活性和可维护性。

design_pattern_principle.png

设计模式的分类

根据目的和用途的不同,设计模式通常被分为三大类:

  • 创建型模式(Creational Patterns):这些模式与对象的创建有关,它们试图将系统中的对象创建机制抽象化,使系统独立于如何创建、组合和表示其对象。

  • 结构型模式(Structural Patterns):这些模式处理类或对象的组合,即如何将不同的类和对象组合在一起以形成更大的结构。它们有助于定义实体之间的关系。

  • 行为型模式(Behavioral Patterns):这些模式关注的是类或对象之间的通信,即它们之间如何分配职责和协作。它们涉及算法和对象间责任的分配。

23种设计模式概览

以下是 GoF(Gang of Four)提出的 23 种经典设计模式的简要介绍:

创建型模式

  • 单例模式(Singleton):确保一个类只有一个实例,并提供全局访问点。

    详细内容请见这篇文章: 设计模式 - 单例模式

  • 工厂方法模式(Factory Method):定义一个用于创建对象的接口,让子类决定实例化哪一个类。

    详细内容请见这篇文章: 设计模式 - 工厂方法模式

  • 抽象工厂模式(Abstract Factory):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

    详细内容请见这篇文章: 设计模式 - 抽象工厂模式

  • 建造者模式(Builder):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

    详细内容请见这篇文章: 设计模式 - 建造者模式

  • 原型模式(Prototype):用原型实例指定创建对象的种类,并且通过复制这个原型创建新的对象。

    详细内容请见这篇文章: 设计模式 - 原型模式

结构型模式

  • 适配器模式(Adapter):将一个类的接口转换成客户希望的另一个接口。

    详细内容请见这篇文章: 设计模式 - 适配器模式

  • 桥接模式(Bridge):将抽象部分与它的实现部分分离,使它们都可以独立变化。

    详细内容请见这篇文章: 设计模式 - 桥接模式

  • 组合模式(Composite):将对象组合成树形结构以表示“部分-整体”的层次结构。

    详细内容请见这篇文章: 设计模式 - 组合模式

  • 装饰器模式(Decorator):动态地给一个对象添加一些额外的职责。

    详细内容请见这篇文章: 设计模式 - 装饰器模式

  • 外观模式(Facade):为子系统中的一组接口提供一个一致的界面。

    详细内容请见这篇文章: 设计模式 - 外观模式

  • 享元模式(Flyweight):运用共享技术有效地支持大量细粒度的对象。

    详细内容请见这篇文章: 设计模式 - 享元模式

  • 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。

    详细内容请见这篇文章: 设计模式 - 代理模式

行为型模式

  • 责任链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合。

    详细内容请见这篇文章: 设计模式 - 责任链模式

  • 命令模式(Command):将请求封装成对象,从而使你可以用不同的请求对客户进行参数化。

    详细内容请见这篇文章: 设计模式 - 命令模式

  • 解释器模式(Interpreter):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

    详细内容请见这篇文章: 设计模式 - 解释器模式

  • 迭代器模式(Iterator):提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露其内部的表示。

    详细内容请见这篇文章: 设计模式 - 迭代器模式

  • 中介者模式(Mediator):用一个中介对象来封装一系列的对象交互。

    详细内容请见这篇文章: 设计模式 - 中介者模式

  • 备忘录模式(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

    详细内容请见这篇文章: 设计模式 - 备忘录模式

  • 观察者模式(Observer):定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。

    详细内容请见这篇文章: 设计模式 - 观察者模式

  • 状态模式(State):允许一个对象在其内部状态改变时改变它的行为。

    详细内容请见这篇文章: 设计模式 - 状态模式

  • 策略模式(Strategy):定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。

    详细内容请见这篇文章: 设计模式 - 策略模式

  • 模板方法模式(Template Method):定义一个操作中的算法骨架,而将一些步骤延迟到子类中。

    详细内容请见这篇文章: 设计模式 - 模板方法模式

  • 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作。

    详细内容请见这篇文章: 设计模式 - 访问者模式

设计模式间的关系

设计模式并不是孤立存在的;相反,它们常常相互补充和支持。例如:

  • 工厂模式单例模式 可以结合使用,以便安全地创建唯一的实例。
  • 装饰模式 可以增强 组件模式 中的元素功能,而不影响其他组件。
  • 策略模式状态模式 在某些方面非常相似,但它们解决的问题不同——前者用于选择算法,后者用于管理状态转变。

理解设计模式之间的关系有助于更好地选择适当的模式组合来解决问题,并能够灵活应对不同的编程需求。同时,了解这些关系还可以帮助我们识别何时不应该过度使用设计模式,避免引入不必要的复杂性。

通过掌握设计模式,开发者可以获得一套强大的工具,用于改进软件架构的质量,提升代码的可读性和可维护性。

0

评论区