设计模式简介
梳理面向对象设计原则、创建型、结构型和行为型设计模式及各模式的基本用途
设计模式是面向对象系统的代码设计思想,核心思想是提供可复用的解决方案,让代码更易维护、扩展和理解。设计模式独立于具体编程语言,不同编程语言特性差异很大,有的语言本身就是为了贯彻某个设计原则而被开发出来的,有的语言提供了针对某些设计模式的语法糖,同一种设计模式在不同语言中也可能有不同的实现方式。
代码的设计其实自底向上分为三层,最基本的是低耦合高内聚的设计思想,往上是面向对象的设计原则,再往上才是各种设计模式。设计模式依赖接口这个抽象规范,接口是抽象方法的集合,在底层实现接口时,必须按照接口给定的调用方式来实现,而对高层模块则隐藏了类的内部实现。
面向对象的设计原则
面向对象的三大法则是封装继承多态,三者是递进关系。封装就是有意识地把对象的属性和方法分为对内的和对外的;继承是为了提高代码的复用性,子类可以直接复用父类的属性和方法,并可以实现新功能或覆写父类方法的实现;多态指同一操作作用于不同对象时,会产生不同的执行结果。
面向对象的设计原则包括:
- 开放封闭原则:对扩展开放,对修改关闭,即支持加新功能,但最好不要修改已经成型的代码。
- 里氏替换原则:引用父类的对象要能透明地使用其子类的对象,即子类和父类的方法,实现上可以不同,但输入和返回需要一致。
- 依赖倒置原则:高层模块不应该依赖底层模块,两者应该依赖接口这个抽象。抽象不应该依赖细节,细节应该依赖抽象,即要针对接口而不是针对实现编程。
- 接口隔离原则:客户端不应该依赖那些它不需要的接口,因此要使用多个专门的接口而不是单一的总接口。
- 单一职责原则:一个类只负责一项职责,不要存在多个导致类变更的原因。
设计模式分类
设计模式大致分为创建者模式、结构型模式、行为型模式。创建者模式解决如何创建对象的问题;结构型解决对象之间怎么组织的问题;行为型模式解决如何实现方法的问题。
- 创建者模式:简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式、单例模式
- 结构性模式:适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式、代理模式
- 行为型模式:解释器模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式、模板方法模式
创建者模式
简单工厂模式:通过工厂类负责创建产品类的实例,隐藏创建对象的实现,但违反了单一职责原则和开闭原则。
工厂方法模式:将工厂分为抽象工厂角色和具体工厂角色,一个工厂角色只负责创建一个产品类的实例。
抽象工厂模式:每一个具体工厂都生产一套产品而不是一个,有利于维护产品之间的约束关系,但难以支持新种类的抽象产品。
建造者模式:用指挥者角色以同样的构建过程创建不同的表示,有利于约束构建顺序。
原型模式:对于需要被复制的类,从内部提供克隆的接口方法,使得在某些属性和方法对外部不可见的情况下,外部也能对类进行复制。
单例模式:保证一个类只有一个实例并提供一个全局的访问点,相当于全局变量的同时防止了命名空间被污染。单例模式分饿汉式和懒汉式,饿汉式即在类加载时进行实例化,懒汉式即在第一次使用时进行实例化。
一般来说,以简单工厂或工厂方法开始,当发现设计需要更大的灵活性时,再向抽象工厂或建造者演化。
结构性模式
适配器模式:使得原本由于接口不兼容而不能一起工作的类可以一起工作,实现方式有多继承(类适配器)和组合(对象适配器)两种,多继承即同时继承多个类,组合即将要适配的类作为适配器的属性,以在适配器中调用需要的属性和方法。
桥接模式:将一个实物的两个维度分离成抽象和实现,将继承关系转换为组合关系,两个维度都可以独立扩展,提高了扩展的灵活性。
组合模式:将对象组合成树形结构,使得用户对单个对象和组合对象的使用具有一致性,角色包括抽象组件、叶子组件、复合组件。
装饰模式:在不改变原有对象结构的前提下,动态地给对象添加额外功能。它通过创建一个包装类(装饰器)来包裹原始对象,允许在调用原始对象方法的前后添加新的行为,同时保持接口的一致性。
外观模式:定义高层接口来统一调用子系统中的功能,使得子系统组合起来的功能更易于使用,实质是多一层封装。
享元模式:通过共享技术减少系统中对象的数量,节省内存空间并提高性能;适用于存在大量相似或相同对象的场景,通过复用已存在的对象来避免重复创建,仅在必要时才创建新对象。
代理模式:为真实对象提供一种代理来以控制这个对象的访问,角色包括抽象实体(作为接口)、实体(真实对象)、代理(和真实对象使用一致的代理对象);常见的应用场景如远程代理、虚代理、保护代理。
行为型模式
解释器模式:一般用于做编译器,解释器是负责解释文法规则的模块,解释器模式是一种语法解释器的开发框架。
责任链模式:使多个对象连成一条链并沿着这条链传递请求,链上的对象都有机会处理请求,避免在客户端处理发送者和接收者之间的耦合关系,一个对象无需知道是其它哪一个对象处理其请求,要求链上的对象有同样的处理接口并存储链的下一级对象。
命令模式:一般用于做桌面程序、命令行工具等,将请求转换为一个包含与请求相关的所有信息的独立对象。将对象的具体实现(行为的实现者)通过接口与业务逻辑(行为的请求者)分离。
迭代器模式:一般用于实现迭代器这种数据结构,将遍历逻辑与聚合对象分离,使得同一聚合对象可以支持多种遍历方式,同时遍历方式的变化不会影响聚合对象本身。
中介者模式:减少对象之间混乱无序的依赖关系,限制对象之间的直接交互,迫使它们通过中介者对象进行合作。
备忘录模式:允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态,用于实现对象的 “快照” 功能和撤销操作。核心结构包括原发器(可以创建备忘录或从备忘录恢复)、备忘录(存储原发器的内部状态,对除了原发器之外的外部隐藏细节)、负责人(管理备忘录的存储和获取,但不直接操作备忘录中的状态)。
观察者模式:又称发布订阅模式,当一个对象的状态改变时,所有依赖它的对象都得到通知并被自动更新,角色包括抽象发布者、具体发布者、抽象观察者、具体观察者。
状态模式:将对象在不同状态下的行为封装到独立的状态类中,使得对象的状态变化时,其行为能自动切换到对应状态的实现,从而避免使用大量的条件判断。内部状态需抽象,行为与状态匹配,不同状态关联不同行为导致不同表现效果。状态模式是状态机思想的一种实现方式。
策略模式:封装一系列可相互替换的算法,算法独立于使用它的客户而变化,即提供相同行为的不同实现,角色包括抽象策略、具体策略和上下文,但客户必须了解不同的策略。
访问者模式:在不修改已有类的前提下,为一组不同类型的对象添加新的操作。它通过将操作逻辑与对象结构分离,使得操作可以独立于对象而变化。定义一个访问者对象,来访问一组不同类型的元素,并对每个元素执行特定操作,而无需在元素类中直接实现这些操作。
模板方法模式:定义一个操作中的算法骨架,而将一些步骤延迟到子类中,可以在不改变算法结构的情况下可重定义操作的某些步骤。角色包括抽象的原子操作/钩子操作(实现模板方法作为算法的骨架)和具体类(实现原子操作)。


