23种设计模式
单例模式
核心定义 一个类只有一个实例 且自行实例化并向系统提供这个实例
注意具体实例化时的多线程安全问题 通常采用饿汉或者懒汉模式
扩展的少量实例具体实现
若采用单例模式记录状态值 应注意垃圾回收机制带来的问题 可采用由容器管理单例 或者 异步记录 或者 观察者的方式 记录状态后落盘
工厂模式
核心定义 通过定义产品接口约束产品共性 定义工厂接口生产产品 同时分别实现产品和工厂接口 通过反射的方式 对调用者屏蔽创建具体对象的细节 根据类返回对象
若一个功能模块中仅需要一个工厂 则采用简单工厂模式 即直接生成工厂对象 且提供静态方法
扩展延迟初始化功能 在工厂内部保持产品状态 可通过map方式保存 需要时若map内存在 则返回 不存在则创建并返回 在此基础上 可以限制产品数量等需求 例如线程池最大数
抽象工厂模式
核心定义 多个产品 且不同产品间存在相同点 如下图所示
代码框架如下图所示
抽象类AbstractCreator类定义创建AbstractroductA及AbstractroductB的方法 Creator1及Creator2类继承抽象类分别实现对所有对应等级产品的创建逻辑 AbstractProductA及AbstractProductB抽象类定义同类产品的共性和个性方法 具体产品类继承抽象类实现个性细节
抽象工厂模式适合横向扩展 即继承AbstractCreator抽象类的实现类的扩展 不能纵向扩展 即修改AbstractCreator抽象类内部方法 因此若采用该种模式 应在设计时确定哪种为横向 哪种为纵向 方便在未来新增功能
模板方法模式
核心定义 抽象类定义基本方法及模板方法 其中模板方法禁止覆写 模板方法顺序调用基本方法 实现类继承抽象类 实现基本方法细节
特点在于模板方法顺序调用基本方法
建造者模式
核心定义 按照需求顺序组装产品类零件 并对外提供封装后的具体产品类
代码框架如下所示
CarModel抽象类采用模板模式 CarBuilder抽象类定义建造者方法 具体建造者类继承抽象建造者类 导演类根据需求具体建造者类及建造顺序新建对象 对外屏蔽实现细节
建造者模式适用相同方法不同顺序产生不同的结果的类 而工厂模式适用生产类
代理模式
核心定义 为被代理类提供代理用于控制被代理类的访问以及增强处理
静态与动态代理的区别在于编码阶段是否可知代理对象 具体使用场景如AOP
jdk动态代理仅可用于接口 cglib可用于类
具体代码如下图所示
用户接口及实现类 静态代理类 动态代理 场景类原型模式
核心定义 实现cloneable接口覆写clone方法 通过堆内存中的二进制流复制对象
用于类重复场景
clone方法不调用构造函数 使用浅拷贝 即可变成员变量会引用同一对象 应注意安全问题
中介者模式
核心定义 将多个类之间一对多相互的耦合转换为统一对中介者类的一对一耦合
适用于类图中出现网状结构且彼此行为有可能发生改变 MVC框架采用中介者模式
中介者模式同时会导致中介者类过于庞大
代码框架如下图所示
定义抽象类AbstractMediator持有具体同事类对象及核心执行方法exec
定义抽象类AbstractColleague持有抽象中介者类
具体同事类调用父类中中介者类exec方法表示发送请求
命令模式
核心定义 场景类通过具体命令类统一传递给调用者 调用者执行命令 命令类维护接受者类 接受者类实现逻辑
代码框架如下图所示
注意每个命令对应一个类 因此会产生命令过多情况下类过多情况
责任链模式
核心定义 将请求按照链表的方式逐级处理 对于调用方仅需调用链首节点开始传递消息即可
适用通过扩展节点至链表尾部 在不改变源码的情况下 增强功能
具体代码如下
请求类 请求等级 处理节点抽象类 处理节点实现类 场景类处理节点父类负责选择合适节点处理 处理节点子类则只需关注处理逻辑
装饰模式
核心定义 抽象装饰类继承抽象被修饰类并通过构造函数维护被修饰类 具体抽象类继承抽象装饰类
适用多重子类继承情况
具体代码如下所示
抽象被装饰类及具体被装饰类 抽象装饰类及具体装饰类 场景类策略模式
核心定义 抽象策略类定义抽象方法 具体抽象类继承抽象策略类 角色类维护抽象策略类并对外提供调用方法
代码框架如下所示
当策略超过4个 应当结合工厂模式的混编模式
适配器模式
核心定义 通过中间类解决两个类或接口不兼容问题
若新业务类单一 则适配器类采用继承方式 否则若新业务类多个 采用聚合方式 即适配器类维持多个新业务类
具体代码框架如下
迭代器模式
极古老模式 不需要学习使用 略过
组合模式
核心定义 通过抽象类定义公共方法 各子类继承抽象类实现个性方法 整体实现树形结构
代码框架如下图所示
观察者模式
核心定义 被观察者类触发动作同时通知观察者类方法
若仅一对观察与被观察对象 可采用函数作参数通过回调方式实现
若被观察与观察者关系为一对多 则通过被观察者实现Observable接口在具体方法中通知观察者
门面模式
核心定义 子系统对外通过门面类进行控制访问 不参与逻辑处理 例如子系统方法调用顺序
当多个门面类时 作用范围小的门面类应当持有作用范围大的门面类 通过调用大范围门面类提供方法 避免重复代码
备忘录模式
核心定义 发起者类拥有当前对象 备忘录类通过map维持单个发起者多状态 备忘录管理者类通过map维持多个备忘录状态
代码框架如下图所示 不完全准确
访问者模式
核心定义 定义抽象被访问者类包含公共属性及接受方法 具体被访问者类实现个性属性及方法 访问者接口定义访问具体被访问者类方法 具体访问者类实现访问细节
代码框架如下图所示
将数据处理从面向过程转化为面对对象的方式 同时将底层模块的数据处理转移到高层模块的数据处理上 保持单一职责原则
适用遍历对象下的属性处理
在该模式中注意区分静态绑定和动态绑定的区别
状态模式
核心定义 状态类与上下文类互相持有对象 表现为1对多的关系 通过上下文类对状态类的改变 从而表现出对外部的行为的改变
具体代码如下所示
抽象状态类 具体状态类 上下文类 场景类抽象状态类持有上下文类对象及定义所有空的状态转换方法 具体状态 类覆写相应状态转换方法 上下文类持有所有具体状态类及当前状态 提供所有状态转换方法
解释器模式
核心定义 定义多个抽象解释器类并由具体解释器类实现细节
由于有许多开源框架或脚本语言可代替 该模式不常用
享元模式
核心定义 将实体类中内部状态及外部状态剥离 以外部状态组合的方式存放享元池 从享元池获得数据后再填充内部状态 从而大量减少重复元素
适用场景为大量相似对象
抽象类 实体类 享元池类 场景类桥接模式
核心定义 抽象与实现解耦
代码框架如下图所示