这是我参与「第五届青训营 」伴学笔记创作活动的第 19 天
创建型模式
- 将对象的创建过程和使用过程进行分离
- 创建型模式更加关注对象的创建过程
- 创建型模式,更加符合单一职责,外界只需要知道他们的共同接口即可
简单工厂模式
别名:静态工厂方法模式
问题:只需要某个参数,就可以获得相应的对象,这个工厂方法定义为 static 类型。
定义:根据不同的参数获取不同类的实例,这些不同的类通常都有相同的父类。
类图:
优点:
- 只关心创建过程,不关心具体业务,符合单一职责
- 增加新的产品只需要,新增具体的产品并且修改工厂方法
- 简单,只需要简单调用类的静态方法,传入参数即可
- 降低了系统的耦合度,增加灵活性。实际开发中,传入的参数可以在配置文件中,进一步降低了系统耦合度
缺点:
- 工厂类承担了所有产品的创建逻辑,职责过重
- 增加了系统中类的个数,增加了系统的复杂度
- 系统扩展困难,违背开闭原则
工厂方法模式
别名:虚拟构造器,多态工厂
定义:工厂父类负责定义创建产品对象的公共接口,类的实例化操作延迟到子类。
类图:
优点:
- 向客户隐藏具体产品类实例化的具体细节
- 让工厂自主确定实例化何种产品对象
- 完全符合开闭原则,可以在不修改工厂角色的前提下引进新的产品
缺点:
- 复杂度增加,类的个数随着产品类型的增加,成对增加
- 增加系统的理解难度
抽象工厂模式
别名:Kit模式
概念:
- 产品等级结构:产品的继承结构
- 产品组:同一个工厂生产的不同产品等级结构的一组产品
定义:提供一个创建一系列相关或者依赖对象的接口,而无需指定它具体的类。
类图:
优点:
- 隔离了具体类的生成
- 保证客户可以始终使用同一个产品组的对象
- 符合开闭原则。在产品组一侧符合开闭原则,只需要简单增加工厂即可
缺点:
- 增加新的产品等级结构比较复杂,违背开闭原则
使用条件:
- 不依赖于产品实例如何被创建,组合和表达的细节
- 每次只使用某一产品组
- 属于同一产品组的产品将在一起使用
- 产品等级结构稳定
三种工厂模式对比
三个模式都属于工厂模式,含义就是使用工厂生产产品。
将生产产品的一个或者一系列方法封装到一个类中,这样的类叫做工厂类;被实例化的类那就是产品类。
-
简单工厂
优点:简单,静态工厂方法,可以创建所有类型的产品
缺点:职责重,单个类复杂度高;不符合开闭原则
描述:支持同一等级结构中的任意产品,不支持扩展增加产品
-
工厂方法
优点:降低工厂的负担;完全符合开闭原则
缺点:类的个数成对增加;对于形成产品族的情况处理复杂
描述:支持同一等级结构的固定产品(支持扩展增加产品)
-
抽象工厂
优点:针对产品族场景的优化;产品组符合开闭原则
缺点:模式复杂,只适用于产品族的场景
描述:支持不同产品族的全部产品(不支持增加产品类型,支持增加产品族)
建造者模式
定义:将一个复杂对象的构建,与它的表示分离,使得同样的构建过程创建不同的表示。建造者模式就是一步一步构建一个复杂的对象,它允许用户只通过指定的类型和内容就可以构建他们,用户不需要知道内部的具体构建细节。
类图:
优点:
- 将产品的创建过程和产品的表示解耦,使得创建过程可以创建不同的产品对象
- 可以很方便的创建具体的建造者或者增加新的具体建造者,符合开闭原则
- 便于更加精细的控制产品的创建过程
缺点:
- 产品之间差异很大,不适合使用建造者模式
- 如果产品内部变化复杂,可能会需要定义很多具体建造这类来适应这种变化
场景:
- 需要生成的对象有很复杂的内部结构
- 需要生成的对象属性存在相互依赖
- 对象的创建过程独立于创建该对象的类
- 隔离复杂对象的创建和表示
原型模式
定义:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象
工作原理:
- 通过请求原型对象复制自己来实现创建的过程
- 工厂类就是原型自身,工厂方法是负责对象的克隆方法
- 克隆创建的对象是全新的对象,有独立的内存空间
- 原型模式可以得到一系列相似但是不完全相同的对象
类图:
优点:
- 简化对象的创建过程,提高新实例的创建效率
- 扩展性比较好
- 简化创建结构,简单的一个方法可以克隆出一的新的对象
- 可以使用深拷贝的方式来保存对象的状态
缺点:
- 需要为每一个类实现克隆方法,对已有的类进行改造时,需要修改源代码,违背了开闭原则
- 深拷贝的方式需要编写较为复杂的代码
场景:
- 创建新对象成本比较大,可以通过复制对象来获得
- 需要保存对象的状态,而且对象的状态变化小
- 避免使用分层次的工厂类来创建分层次的对象
扩展:
- 原型管理器
单例模式
定义:确保一个类只有一个实例,而且自行实例化并且向整个系统提供这个实例。
类图:
优点:
- 对唯一实例受控访问
- 节约资源,提高系统性能
- 允许可变数量(有限个)的实例(多例模式)
缺点:
- 扩展困难(缺少抽象层)
- 单例类职责重。一个业务类不应该关心自己是不是单例,但是单例模式要把模式和业务混合在一起
- 垃圾回收机制,可能导致共享单例对象的状态丢失
场景:
- 系统只需要一个这个类的实例,或者资源只允许创建一个对象实例
- 客户调用类的单个实例,只允许使用一个公共访问点