一、设计模式分类(共23种)
-
创建型模式:为了更灵活的创建对象,提升已有代码的灵活性和可复用性。
-
结构型模式:将对象和类组装成较大的结构,并同时保持结构的灵活和高效。
-
行为模式:对象间的高效沟通和职责委派。
1、创建型模式
设计模式 | 定义 | 应用场景 |
---|---|---|
工厂方法模式 | 在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。 | 需要创建多个相似对象 |
抽象工厂模式 | 创建一系列相关的对象,而无需指定其具体类 | 提供一组方法来创建多个相似对象,或者多个对象有相同约束条件 |
单例模式 | 保证一个类只有一个实例,并提供一个访问该实例的全局节点。 | 保证对象唯一 |
建造者模式 | 分步骤创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。 | 对象有多个组成部分,并且需要控制对象的组装 |
原型模式 | 复制已有对象,而又无需使代码依赖它们所属的类。 | 需要多次复制对象,或者需要将对象的信息提供给外部,但是不让外部进行修改 |
2、结构型模式
设计模式 | 定义 | 应用场景 |
---|---|---|
代理模式 | 能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。 | 控制对象访问 |
适配器模式 | 能使接口不兼容的对象能够相互合作。 | 需要将两个接口不兼容的对象进行转换 |
装饰模式 | 通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。 | 需要扩展一个类的功能。 |
外观模式 | 能为程序库、框架或其他复杂类提供一个简单的接口。 | |
组合模式 | 可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。 | 从一个整体中能独立出部分模块或者功能 |
享元模式 | 通过共享多个对象所共有的相同状态,让你能在有限的内存容量中载入更多对象。 | 存在大量相似对象,需要缓冲池的场景 |
桥接模式 | 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用。 |
3、行为模式
设计模式 | 定义 | 应用场景 |
---|---|---|
策略模式 | 让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。 | 对于同一问题有多种处理方式 |
责任链模式 | 允许你将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。 | 多个对象处理同一请求 |
观察者模式 | 定义对象间一对多的依赖挂你,使得当对象改变状态时,所有依赖 于它的对象都会得到通知并更新。 | 消息监听的场景 |
模板方法模式 | 在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 | 多个子类有公有方法,调用逻辑相似 |
中介者模式 | 减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作。 | 适用于多个对象之间耦合紧密的情况 |
状态模式 | 能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。 | 对象含有多种状态,存到多种判断语句,行为会随着状态改变 |
解释器模式 | 做各种各样的解释器 | 需要将语句表示为一个抽象语法树 |
命令模式 | 将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中, 且能实现可撤销操作。 | 存在命令的场景 |
备忘录模式 | 允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。 | 需要保存并恢复一个对象在某一时刻的状态 |
迭代器模式 | 能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。 | 遍历一个容器对象 |
访问者模式 | 能将算法与其所作用的对象隔离开来 | 对象结构稳定,经常需要在此对象结构上定义新的操作 |
二、 六大设计原则
高内聚、低耦合
1、单一职责原则
定义:有且只有一个原因引起类的改变
-
接口要小,每个接口实现一个职责
-
单一职责适用于接口、类、方法,但是实际情况下类很难实现单一职责。
2、里氏替换原则
1、定义:所有引用基类的地方必须能透明的使用其子类的对象
-
里氏替换的核心是抽象,抽象又依赖继承(尽量用组合代替继承)。
-
父类出现的地方子类就可以出现,并且替换为子类不会产生任何错误,使用者不需要知道调用的是子类还是父类。反过来子类出现的地方,父类未必就能出现
2、特点:
-
子类必须完全实现父类方法
-
子类可覆写父类方法
-
覆盖或实现父类方法时输入参数可被放大(子类方法的入参必须跟父类被覆写的方法入参相同或者更加宽松)
-
覆写或实现父类方法的返回值可以被缩小
3、继承的优点:
-
代码复用,减少创建类的成本
-
提高代码的可扩展性
4、继承的缺点:
-
继承是侵入性的,只要继承就必须拥有父类的所有属性和方法
-
可能造成子类灵活性的降低,增强了耦合性
3、依赖倒置原则
定义:
-
高层模块不应该依赖于底层模块,两者应该依赖其抽象
-
抽象不应该依赖细节,细节应该依赖抽象 (抽象指的是接口或者抽象类,细节指的是具体实现)
-
实现类之间不该发生依赖关系,依赖关系通过抽象或者接口产生
4、接口隔离原则
定义:类不要依赖用不到的接口,接口尽量细化
5、迪米特原则
定义:
一个类应该对自己需要耦合或者调用的类知道的最少(调用的逻辑尽可能少)
-
只跟直接耦合的对象沟通(指组合、聚合、依赖关系)
-
不要对外暴露不必要的public和静态方法
6、开闭原则
定义:
一个实体如类、模块、函数应该对扩展开放、对修改关闭(主要是针对抽象类)
-
通过接口或抽象类约束拓展,并且尽量保持稳定
-
将相同变化封装到同一接口或抽象类,不同变化封到不同接口或抽象类中