总述
设计模式的主要作用就是对代码解耦,不同的设计模式解耦的目标不同
- 创建型模式:解决对象创建的问题
- 结构型模式:解决类之间组合的问题
- 行为型模式:解决类之间交互的问题
创建型模式
包括单例模式、工厂模式、建造者模式、原型模式
单例模式(Singleton Pattern)
特征
一个类只允许创建一个对象
使用场景
- 创建无状态的对象时
- 创建全局唯一的对象时
实现方式对比
懒汉式、饿汉式、双重检测、静态内部类、枚举
懒汉式、双重检测、静态内部类都是懒加载,在使用时创建对象,如果创建对象的过程复杂耗时,启动后首次使用性能会下降
饿汉式、枚举相当于预热,启动时将对象创建好,会导致启动变慢,但使用的时候就直接用了
个人更倾向于饿汉式和枚举
工厂模式(Factory Pattern)
特征
通过一个新的类,专门用来创建某一类对象,他们一般使用了多态的特性,是一个接口和对应的一批实现类
使用场景
- 对象的创建过程较复杂时
实现方式对比
- 简单工厂:仅仅将对象的创建抽到一个新类中,这个新类就是工厂
- 工厂方法:提供一个接口和一批对应的实现类,每个实现类都用来创建对应的对象,这个接口就是工厂的接口,实现类就是工厂的实现类
- 抽象工厂:一个工厂提供多个方法,分别负责创建不同维度的对象
当仅仅是选择创建哪个对象的过程比较复杂时,使用简单工厂模式
当对象本身的创建过程都很复杂时,使用工厂方法模式
当对象的维度过多,不同维度的排列组合使实现类爆炸时,使用抽象工厂模式
抽象工厂好像也就支持到二维,再多维度就不好用了,抽象工厂本身也不太常用
建造者模式(Builder Pattern)
特征
先创建建造者对象,赋值后再通过构建方法创建目标对象
使用场景
- 构造函数的必填参数过多
- 在构建时校验参数有效性,避免对象处于无效状态
- 防止对象创建后修改,屏蔽 set 方法
原型模式(Prototype Pattern)
特征
利用已有对象,通过拷贝创建新对象
使用场景
创建对象时,属性值需要通过IO、复杂计算等耗时操作获取
实现方式对比
浅拷贝:基本属性复制值,对象属性复制内存地址
深拷贝:基本属性复制值,对象属性要求创建新对象(拥有新内存地址)
一般对象(包括集合)都用深拷贝,防止后续操作修改原始对象属性
结构型模式
包括代理模式、桥接模式、装饰器模式、适配器模式、门面模式、组合模式、享元模式
代理模式(Proxy Pattern)
特征
新类封装原始类的方法,提供相同的方法签名
使用场景
给原始类附加无关的功能
桥接模式(Bridge Pattern)
特征
将实体的不同维度分离并抽象,将一个维度作为另一个维度的属性进行方法调用,以实现维度叠加的组合功能
使用场景
类的特征维度过多,维度的组合导致实现类爆炸
装饰器模式(Decorator Pattern)
特征
新类和原始类继承相同父类,通过嵌套调用,实现功能的增强
使用场景
从多个方向对原始类的同一个功能进行增强,方向的组合导致继承类爆炸
适配器模式(Adapter Pattern)
特征
新类封装原始类的方法,提供不同的方法签名
使用场景
- 封装有缺陷的接口
- 统一多个功能相同的接口协议
- 兼容老版本接口
门面模式(Facade Pattern)
特征
新类调用多个原始类的接口,对外提供一个新的接口
使用场景
- 多个接口的调用太过复杂,可以封装为一个新接口,调用更简单
- 多个接口调用性能有问题,可以封装为一个新接口,减少调用次数,减少网络IO消耗
组合模式(Compose Pattern)
特征
让具有父子关系的类实现相同接口
使用场景
类具有父子关系,统一他们的操作行为
享元模式(Flyweight Pattern)
特征
将具有固定属性的对象复用
使用场景
频繁创建拥有完全相同的属性的对象
行为型模式
包括观察者模式、模板模式、策略模式、责任链模式、状态模式、迭代器模式、访问者模式、备忘录模式、命令模式、解释器模式
观察者模式(Observer Pattern)
特征
多个观察者类实现相同的抽象接口,并注册到被观察者中,被观察者以调用抽象接口的形式,循环调用这些观察者
使用场景
当对象之间存在一对多关系,且多个对象之间互相独立的时候
模板模式(Template Pattern)
特征
父类作为抽象类对外提供通用方法,方法内部调用自身抽象方法,子类实现抽象方法
使用场景
方法的某几部分通用,而另外的部分根据不同场景有不同实现
策略模式(Strategy Pattern)
特征
有一个策略接口和对应的一组策略实现类,根据不同条件选择不同策略类执行
使用场景
ifelse分支过多,且分支逻辑之间没有先后顺序,且目的相同
责任链模式(Chain Of Responsibility Pattern)
特征
定义一个接口和一组对应实现类,在新类中注册这些实现类并循环调用他们,调用成功就退出
使用场景
ifelse分支过多,且分支逻辑之间可能会互相影响,且有序
实现方式
- 某个实现类中的逻辑执行成功就break
- 所有实现类的逻辑都执行一遍
状态模式(State Pattern)
特征
遇到事件后,将每个状态的变更和动作的执行都放到单独的类里执行
使用场景
对象的行为依赖其状态
迭代器模式(Iterator Pattern)
特征
将容器的属性和迭代行为分到两个不同的类中
使用场景
顺序访问容器的每个属性
访问者模式(Visitor Pattern)
特征
定义一个接口和一组对应的实现类,作为被操作对象,也就是被访问者
定义另一个接口和对应的一组实现类,对所有目标分别定义一个访问接口,每个访问者实现类都是一个操作维度,实现所有目标的操作细节
使用场景
被访问的目标个数几乎不变,而他们对应的操作经常变化
备忘录模式(Snapshot Pattern)
特征
独立出一个快照类,专门封装快照的数据和存取,然后集成进原始逻辑中
使用场景
记录一个对象的内部状态
命令模式(Command Pattern)
特征
有一个命令接口和一组对应的命令实现类,根据不同条件选择不同命令类执行
使用场景
ifelse分支逻辑过多,且每个分支的目的是不同的
解释器模式(InterPreter Pattern)
特征
提供一个解释器接口和一组对应的实现类,内部封装不同的语法解析规则
使用场景
提供特定的语法解析功能
中介模式(Mediator Pattern)
特征
提供一个组件父类和一组对应的子类,将子类之间的交互封装到一个单独的对象中
使用场景
子类之间交互错综复杂,某一个子类的动作会按顺序触发其他很多子类的行为