前言
一切设计都为了代码的可扩展性和可读性,都为了应对变化!
我们是基于设计原则的思想,来选择设计模式去实现,代码可读,可扩展的目标!
1 设计原则
1.1 开闭原则(Open-Closed Principle, OCP)
核心设计思想:对扩展开放,对修改关闭。
含义:抽象可变功能,可变功能通过子类扩展实现,避免对已有抽象实现的修改。
优点:便于扩展;
1.2 单一职责(Simple Responsibility Pinciple,SRP)
核心设计思想:单个方法或单个类或单个包,应该包含单一的职责
含义:
- 一个方法应该只负责一个功能,如果方法的功能包含很多,代码很臃肿,请将方法进行拆分,主方法负责核心流程,分方法负责具体单个功能点的实现;
- 一个Class类应该只负责一个明确的职责,不要想一个Class把所有事情都做了,比如一个服务层的类,不要把数据层的功能都写在一起
- 一个包应该只负责一个方面的职责,比如dao包下面就是负责数据层服务的
优点:便于扩展;可读性高
1.3 依赖倒置原则(Dependence Inversion Principle,DIP)
设计思想:高层模块不应该依赖底层模块,应该依赖其抽象。
含义:面向接口编程,不要面向实现,比如服务模块代码会使用数据模块的功能,那么服务模块应该内聚的是数据模块的抽象,而不是具体的数据模块实现,这样可以避免因数据模块实现的变动,而导致服务模块的改变。经典应用:Spring的IOC
优点:便于扩展;
1.4 接口隔离原则(Interface Segregation Principle, ISP)
设计思想:接口设计应该具备单一责任要求,即多个单一责任接口替换多责任接口
含义:子类避免继承接口后,被迫实现一些自己不需要的功能,哪怕是空实现,也代表接口设计出现责任非单一的问题。应该把接口细化,按功能划分为多类接口。
优点:便于扩展;可读性高
1.5 迪米特原则(Law of Demeter LoD)/最少知道原则(LKP)
设计思想:一个对象应该对其他对象保持最少的了解
含义:
- 避免无关的依赖,比如A依赖B实现某个功能,B又需要依赖C,那么A完全没必要知道C的存在,那C就不要已中间对象的形式出现在A的功能实现中;
- 控制方法访问权限,即public,protect,default,private,如果方法私有那么一定是private,请按最小原则控制对象的访问权限,对外部对象,应按需暴露方法和属性,越少越好;
优点:便于扩展;可读性高;
1.6 里氏替换原则(Liskov Substitution Principle,LSP)
设计思想:所有引用基类的地方必须能替换为它的任意子类对象,且程序执行效果“不变 ”
含义:子类不要重写父类的非抽象方法,父类只实现通用方法即可。尽量保证继承的有意义,不要乱用继承,来实现非继承功能。其实就是少修改,多扩展,也是开闭原则的体现。
优点:可扩展性;可读性高;
1.7 合成复用原则(Composite/Aggregate Reuse Principle,CARP)
设计思想:尽量使用对象组合(has-a)/聚合(contanis-a),而不是继承关系达到功能复用的目的。
含义:里氏替换是强调合理使用继承,如果出现继承无法满足的时候,采用合成复用的方式,而不要去破坏原本的继承关系。
优点:可扩展性;可读性高;
总体来说,都是为了可扩展性和可读性,
核心思想:开闭和单一;
实现方式:依赖倒置、接口隔离、最少知道;
关系约定:里氏替换、合成复用;
2 设计模式:设计原则的体现
2.1 单例模式
- 单一责任:单例么,只负责生产一个产品,有且只有一个功能
2.2 工厂方法|抽象工厂:
- 开闭原则:工厂定义构建产品的超类的通用方法不变,子类工厂扩展实现构建不同子类产品的方法
- 单一责任:每个子类工厂只负责一个类型的产品生产
- 依赖倒置:工厂依赖的是产品的抽象,而不是产品的实现
2.3 建造者模式
- 开闭原则:构建方式不变,但可以扩展实现构建的子项
- 依赖倒置:建造者依赖的是子项的抽象
- 合成复用:建造者通过组合子项的方式来扩展功能
2.4 原型模式
- 单一责任:原型实现克隆接口,仅负责克隆一件事情
2.5 适配器模式
- 开闭原则:提供功能的对象(A)不变,适配目标(B)不变,扩展实现一个适配器(C)使用A来实现目标B的功能
- 单一责任:提供功能的对象,适配目标对象,适配器对象,各自职责唯一
- 合成复用:适配器组合了提供功能的对象
2.6 桥梁模式
- 开闭原则:当部分功能实现有自己的一套扩展机制,为了保证抽象的不变性,让实现化的部分独立扩展
- 单一责任:抽象化与实现化的分离,使得两者责任单一,可以自由发展
- 合成复用:抽象化对象聚合实现化对象,从而获得实现化对象的功能
- 接口隔离:这个体现的太明显了
- 依赖倒置:抽象化对象的抽象依赖实现化对象的超类
2.7 树组模式
- 开闭原则:树组结构不变,通过继承体系自由扩展
- 合成复用:对象本身聚合对象的集合,构成父子节点关系
2.8 装饰者模式
- 开闭原则:装饰结构不变,面向变化扩展的经典实现
- 合成复用:对象本身通过聚合同类对象,实现了功能的扩展
- 单一责任:每一个装饰者仅负责自己独立的功能
2.9 门面模式
- 开闭原则:门面本身对外接口不变,内部通过扩展来应对变化
- 合成复用:门面聚合各类子功能的实现对象
- 单一责任:门面干门面的活,子功能干子功能的事
2.10 享元模式
- 合成复用:享元对象聚合共享对象的集合
- 单一责任:享元对象仅提供访问共享对象的入口,各种功能实现由共享对象完成
2.11 代理模式
- 合成复用:代理对象聚合被代理的对象,从而可以控制被代理对象的功能执行过程
- 单一责任:代理仅负责控制执行过程,不做功能上的附加操作
2.12 责任链模式
- 开闭原则:链表的结构不变,但可以自由的扩展不同的实现
- 单一责任:每个责任链的节点只负责单一的功能
- 合成复用:每个责任链的节点会聚合下一个责任链的节点
2.13 命令模式
- 单一责任:命令、调用者、执行者,各自负责自己的功能
- 合成复用:命令对象聚合执行者对象,调用者对象聚合命令对象
- 最少知道:调用者与执行者解耦,因为通常调用者无需知道执行者的所有行为,他只需知道当前执行的命令相关信息即可
2.14 解释器模式
- 单一责任:就干翻译这一件事,对于被翻译对象而言,他没必要再提供翻译相关的实现,将这个实现交给翻译器即可
2.15 迭代器模式
- 单一责任:就负责迭代访问数据
- 开闭原则:迭代方式通用不变,各个集合实现各自的迭代需求
- 合成复用:每个迭代器默认聚合各自的集合类,通过集合类本身方法实现迭代功能,也是一种适配模式
- 接口隔离:相对于统一的集合接口,他把迭代实现分离
2.16 中介者模式
- 单一责任:嘿嘿,中介就是个负责对象间关系的
- 开闭原则:中介处理关系不变,中介负责的对象,可以自由扩展
- 合成复用:中介聚合相关的对象
2.17 备忘录模式
- 单一责任:为对象信息持久化提供功能,仅此一个功能哦
2.18 观察者模式
- 合成复用:观察者聚合被观察主题(主动获取主题变化);被观察主题聚合被观察者集合(主题主动通知观察者)
- 依赖倒置:两者之间皆是聚合抽象
2.19 状态模式
- 合成复用:对象聚合状态抽象,来实现不同状态下的行为
- 依赖倒置:对象聚合状态的抽象,而非实现
2.20 策略模式
- 合成复用:对象聚合策略抽象,来实现不同策略下的行为
- 依赖倒置:对象聚合策略的抽象,而非实现
2.21 模板方法模式
- 开闭原则:模板抽象通用方法不变,差异化部分,由子类扩展实现
- 里氏替换:父类只实现通用方法,很明显的原则体现
2.22 访问者模式
- 责任单一:访问者就是负责临时“访问”功能,被用于其他对象方法参数依赖
3 总结
心怀扩展,代码易读,原则为本,模式为法。
多读源码!多思考!多动手!gogogo!
爱家人,爱生活,爱设计,爱编程,拥抱精彩人生!