设计模式原则及分类简介

486 阅读8分钟

1. 认识设计模式

软件工程中,设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。这个术语是由埃里希•伽玛等人在1990年从建筑设计领域引入到计算机科学的。

1.1. 设计模式的目的

编写软件的过程中,程序员面临着来自耦合性、内聚性以及可维护性、可扩展性、重用性、灵活性等多方面的挑战,设计模式是为了让程序拥有更好的:

  • 代码可重用性。(相同功能的代码,不用多次编写);
  • 可读性。(编程规范性,便于其他程序员的阅读和理解);
  • 可扩展性。(当需要增加新功能时,非常方便。或者叫可维护性);
  • 可靠性。(当增加新的功能后,对原来的功能没有影响);
  • 使程序呈现高内聚、低耦合的特点。

设计模式包含了面向对象的精髓。“懂了设计模式,你就懂了面向对象分析和设计(OOA/OOD)的精要”

1.2. 设计模式的思想

  • 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起;
  • 针对接口编程,而不是针对实现编程;
  • 为了交互对象之间的松耦合设计而努力。

1.3. 设计模式的原则

设计模式原则,其实就是程序员在编程时,应当遵循的原则,也就是各种设计模式的基础,即设计模式为什么这样设计的依据。

设计模式的七大原则有:

  • 单一职责原则
  • 里氏替换原则
  • 依赖倒置原则
  • 接口隔离原则
  • 迪米特法则
  • 开闭原则
  • 合成复用原则

2. 设计模式原则

2.1. 单一职责原则

Single Responsibility Principle(单一职责原则),简称SRP

定义:应该有且仅有一个原因引起类的变更。也就是说一个接口或类只有一个职责。

好处

  • 类的复杂性降低,实现什么职责都有清晰的定义。
  • 可读性提高。复杂性降低,那当然可读性提高了。
  • 可维护性提高。可读性提高,那当然更容易维护了。
  • 变更引起的风险降低。变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助。

单一职责原则不仅适用于接口、类,同时也适用于方法。接口和方法一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。

单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类的设计是否优良,但是“职责”和“变化原因”都是不可度量的,因项目而异,因环境而异。

2.2. 里氏替换原则

Liskov Substitution Principle(里氏替换原则),简称LSP

定义:只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常。但是子类出现的地方,父类未必就能适应。

含义

  • 子类必须完全实现父类的方法。
  • 子类可以有自己的个性。
  • 覆盖或实现父类的方法时输入参数可以被放大。
  • 覆盖或实现父类的方法时输出结果可以被缩小。

2.3. 依赖倒置原则

Dependence Inversion Principle(依赖倒置原则),简称DIP

含义

  • 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。
  • 接口或抽象类不依赖于实现类。
  • 实现类依赖接口或抽象类。

采用依赖倒置原则可以减少类之间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。

依赖的三种写法

  • 构造函数传递依赖对象(构造函数注入)
  • Setter 方法传递依赖对象(Setter 方法注入)
  • 接口声明依赖对象(接口注入)

2.4. 接口隔离原则

Interface Segregation Principle(接口隔离原则),简称ISP

定义:建立单一接口,不要建立臃肿庞大的接口。也就是说接口尽量细化,同时接口中的方法尽量少。

接口隔离和单一职责的区别

审视角度不相同,单一职责要求类和接口的职责单一,注重的是职责,这是业务逻辑的划分。而接口隔离要求接口的方法尽量少。

例如一个接口的职责可能包含 10 个方法,这 10 个方法都放在一个接口中,提供给多个模块访问,各个模块按照规定的权限来访问,系统外则通过接口文档进行约束,这种设计按照单一职责原则是允许的,按照接口隔离原则是不允许的,它要求的是提供个几个模块使用就应该有几个接口,而不是这种一个接口供所有客户端访问。

2.5. 迪米特法则

Law of Demeter(迪米特法则),简称LoD

也称为Least Knowledge Principle(最少知识原则),简称LKP

定义:一个对象应该对其他对象有最少的了解。

迪米特法则的核心观念就是类间解耦,弱耦合,至于弱耦合了以后,类的复用率才可以提高。

2.6. 开闭原则

Open Closed Principle(开闭原则),简称OCP

定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。也就是说一个软件实体应该通过扩展实现变化,而不是通过修改已有的代码实现变化。

开闭原则是最基础的一个原则,前面的五个原则都是开闭原则的具体形态。可以说开闭原则是抽象类,其他五大原则是具体的实现类。

2.7. 合成复用原则

Composite Reuse Principle(合成复用原则),简称CRP

定义:合成复用原则就是尽量使用合成/聚合的方式,而不是使用继承。

有两个类,A 类和 B 类,现在想让 B 类能够使用 A 类的方法,有几种方式:

  1. B 类继承 A 类。如果我们只是让 B 类去使用 A 类中的方法。使用继承就会使 B 类和 A 类的耦合性增强。
  2. 使用依赖,在 B 类中增加一个方法,方法参数是 A 对象,可以传进来使用。表示 B 类依赖 A 类。
  3. 使用聚合,在 B 类中增加一个成员属性 A a,并提供 setter 方法。表示把 A 类聚合到 B 类中。
  4. 使用组合,在 B 类中增加一个成员属性 A a = new A(),表示把 A 类组合到 B 类中。

3. 设计模式分类

GoF 设计模式分为三种类型,共 23 种。

  • 创建型设计模式,共 5 种(+1)。
  • 结构型设计模式,共 7 种(+1)。
  • 行为型设计模式,共 11 种。

还有另一类设计模式:J2EE 设计模式,共 8 种。

3.1. 创建型设计模式

这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。

  1. 单例模式(Singleton Pattern)
  2. 工厂方法模式(Factory Method Pattern)
  3. 抽象工厂模式(Abstract Factory Pattern)
  4. 建造者模式(Builder Pattern)
  5. 原型模式(Prototype Pattern)

3.2. 结构型设计模式

这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式,旨在解决如何构建灵活且可复用的类和对象结构。

  1. 适配器模式(Adapter Pattern)
  2. 桥接模式(Bridge Pattern)
  3. 组合模式(Composite Pattern)
  4. 装饰器模式(Decorator Pattern)
  5. 外观模式(Facade Pattern)
  6. 享元模式(Flyweight Pattern)
  7. 代理模式(Proxy Pattern)

还有一个设计模式也属于结构型设计模式:过滤器模式(Filter、Criteria Pattern)。

3.3. 行为型设计模式

这些模式关注对象之间的通信和交互,旨在解决对象之间的责任分配和算法的封装。

  1. 责任链模式(Chain of Responsibility Pattern)
  2. 命令模式(Command Pattern)
  3. 解释器模式(Interpreter Pattern)
  4. 迭代器模式(Iterator Pattern)
  5. 中介者模式(Mediator Pattern)
  6. 备忘录模式(Memento Pattern)
  7. 观察者模式(Observer Pattern)
  8. 状态模式(State Pattern)
  9. 策略模式(Strategy Pattern)
  10. 模板模式(Template Pattern)
  11. 访问者模式(Visitor Pattern)

还有一个设计模式也属于行为型设计模式:空对象模式(Null Object Pattern)。

3.4. J2EE 设计模式

这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。

  1. MVC 模式(MVC Pattern)
  2. 业务代表模式(Business Delegate Pattern)
  3. 组合实体模式(Composite Entity Pattern)
  4. 数据访问对象模式(Data Access Object Pattern)
  5. 前端控制器模式(Front Controller Pattern)
  6. 拦截过滤器模式(Intercepting Filter Pattern)
  7. 服务定位器模式(Service Locator Pattern)
  8. 传输对象模式(Transfer Object Pattern)