1 基本概述
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。
这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。
2 使用目的
编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战,使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。
代码重用性 (即:相同功能的代码,不用多次编写)
可读性 (即:编程规范性, 便于其他程序员的阅读和理解)
可扩展性 (即:当需要增加新的功能时,非常的方便,称为可维护)
可靠性 (即:当我们增加新的功能后,对原来的功能没有影响)
使程序呈现高内聚,低耦合的特性
设计模式包含了面向对象的精髓,“懂了设计模式,你就懂了面向对象分析和设计(OOA/D)的精要”
Scott Mayers 在其巨著《Effective C++》就曾经说过:C++老手和 C++新手的区别就是前者手背上有很多伤疤
3 设计模式七大原则
3.1 单一职责原则
- 定义:一个类应该只负责一项职责。
- 解析:如果一个类承担了多个职责,那么当其中一个职责需要更改时,可能会导致其他职责受影响,从而增加了代码维护的风险和复杂度。因此,单一职责原则鼓励将类的不同职责分离到不同的类中。
3.2 接口隔离原则
- 定义:客户端不应该依赖它不需要的接口。
- 解析:该原则强调一个类对另一个类的依赖应该建立在最小的接口上。接口应该是内聚的,即一个接口中的方法应该都是紧密关联的。这样可以减小接口的大小,减少系统的复杂性。
3.3 依赖倒转原则
- 定义:高层模块不应该依赖低层模块,两者都应该依赖抽象。
- 解析:该原则提倡编程时应依赖于抽象而不是具体实现。这样,当具体实现变化时,只需要修改少量代码。同时,这也使得系统更加灵活和稳定。
3.4 里氏替换原则
- 定义:所有引用基类的地方必须能透明地使用其子类。
- 解析:这一原则主要针对继承关系,要求子类可以替换父类并且不影响程序的功能。这确保了继承的使用是正确的,并促进了程序的可扩展性。
3.5 开闭原则
- 定义:软件实体如类、模块和函数应该对扩展开放,对修改关闭。
- 解析:开闭原则要求软件设计能够容易地扩展新功能而不需修改现有代码。这通过抽象和多态来实现,使得系统既灵活又稳定。
3.6 迪米特法则
- 定义:一个对象应当对其他对象保持最少的了解。
- 解析:也被称为“最少知道原则”,迪米特法则旨在降低类之间的耦合度。一个类应避免与无关的类直接交流,以保持系统的模块化和可管理性。
3.7 合成复用原则
- 定义:尽量使用对象组合/聚合而不是继承来达到复用的目的。
- 解析:合成复用原则强调复用的逻辑应当封装在独立的组件中,并通过组合而非继承的方式重用这些组件。这有助于避免继承带来的问题,如父类与子类之间的强耦合。
4 设计模式类型
根据设计模式的参考书 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 中所提到的,总共有 23 种设计模式。这些模式可以分为三大类:
创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式。
结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter 模式)、状态模式、策略模式、职责链模式(责任链模式)。
每个设计模式都有各自的特点
- 创建型模式
- 单例模式:确保一个类只有一个实例,并提供全局访问点。实现方法包括懒汉式和饿汉式。
- 工厂方法模式:提供一个接口创建对象的创建者,让子类决定实例化哪一个类。
- 抽象工厂模式:创建一系列相关或相互依赖的对象接口,无需指定具体的类。
- 建造者模式:使用多个简单的对象一步一步构建成一个复杂的对象。
- 原型模式:通过复制现有的实例来创建新的实例,涉及深拷贝和浅拷贝的问题。
- 结构型模式
- 适配器模式:结合了两个不兼容的接口。
- 桥接模式:抽象与实现的分离,使它们可以独立变化。
- 组合模式:创建对象组的树形结构,以表示“整体/部分”层次结构。
- 装饰器模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活。
- 外观模式:隐藏系统的复杂性,并向客户端提供一个可以访问系统的接口。
- 享元模式:通过共享技术有效地支持大量细粒度的对象。
- 代理模式:为其他对象提供一种代理以控制对这个对象的访问。
- 行为型模式
- 责任链模式:创建一个对象的链,让请求沿着链传递,直到有一个对象处理它为止。
- 命令模式:将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,队列或记录请求日志,以及支持可撤销的操作。
- 解释器模式:实现一个表达式接口,解释一个特定的上下文。
- 迭代器模式:提供一种方法访问聚合对象中各个元素,而又不暴露该对象的内部细节。
- 中介者模式:提供了一个统一的接口,用来管理不同的对象之间的交互。
- 备忘录模式:保存了对象的状态,以便在后期可以恢复。
- 观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
- 状态模式:允许一个对象在其内部状态改变时改变它的行为。
- 策略模式:定义了一系列算法,并将每一个算法封装起来,使它们可以互换。
- 模板方法模式:定义了一个操作中的算法骨架,而将一些步骤延迟到子类中实现。
- 访问者模式:表示一个作用于某对象结构中的各元素的操作。
5 设计模式的应用
- 简化软件设计:设计模式提供了经过验证的解决方案,可以帮助开发者避免重复发明轮子,简化设计过程。
- 提高代码可维护性:通过使用设计模式,可以使代码更加模块化,易于理解和维护。
- 促进代码重用:设计模式强调重用已有的解决方案,减少不必要的开发工作。
6 总结
设计模式的关键在于理解每个模式的核心原理及其解决的特定问题,然后根据实际需求来选择最适合的模式。正确应用设计模式能够显著提高软件的可维护性、扩展性和复用性。