设计模式之禅(六大设计原则)
1.单一职责原则(Single Responsibility Principle)
也就是职责划分要明确,单一职责原则提出了一个编写程序的标准,用“职责”或者“变化原因”来衡量接口或者类设计的是否优良,但是“职责”或者“变化原因”都是不可度量的,因项目而异,因环境而异。
接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。
2.里氏替换原则(Liskov Substitution Principle)
java三大特征:封装、继承、多态
该原则主要针对继承这一关系。
通俗点讲就是:只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误和异常,使用者根本不需要知道是父类还是子类。但是,反过来就不行,有子类的地方,父类未必就能适应。
规范:
- 子类必须完全实现父类的方法
- 子类可以有自己的个性
- 覆盖或实现父类的方法是输入参数可以被放大。子类中的方法的参数必须与超类中被重写的方法的参数相同或者更宽松(注意重载和重写这两个概念)
- 重写或实现父类的方法时输出结果可以被缩小(return<=)
采用里氏替换原则时,尽量避免子类的“个性”,一旦子类有“个性”,这个子类和父类之间的关系就很难调和了
3.依赖倒置原则(Dependence Inversion Principle)
即面向接口编程,传值直接使用接口或者抽象类
规范:
1.每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备
2.变量的表面类型尽量是接口或者抽象类
3.任何类都不应该从具体类派生
4.尽量不要重写基类的方法
5.结合里氏替换原则使用
4.接口隔离原则(Interface Segregation Principle)
何为接口:1.实例接口(new关键字产生一个实例);2.类接口(interface关键字定义的接口)
该原则就是将接口的职责细分,保证接口的纯洁性:
1.接口尽量小(不能违反单一职责原则)
2.接口要高内聚(提高接口、类、模块的处理能力,减少对外的交互。也就是你只用知道结果就好,不用管它是怎么实现的)
3.定制服务(根据客户端来划分接口,按照权限划分接口)
4.接口设计是有限度的(无标准视情况而定)
实践中的规则:
1.一个接口只服务于一个子模块或者业务逻辑
2.通过业务逻辑压缩接口中的public方法,接口要时常去回顾,尽量让接口达到“最小”,而不是“臃肿”的一大堆方法
3.已经被污染的接口,尽量去修改,若变更的风险较大,则采用适配器模式进行转化处理
4.视情况而定,不用盲目抄袭
5.迪米特尔法则(Law of Demeter Principle || 最少知道原则)
直接的朋友:成员变量、方法参数、方法返回值
只和直接的朋友交流。陌生的类最好不用以局部变量的方式出现在类的内部,尽量少对外公布public方法和非静态的public变量,如果一个方法放在本类中,既不增加类间关系,也不对本类产生负面影响,那就放置在本类。(类间解耦,弱耦合)
6.开闭原则(Open Closed Principle)
java世界中最基础的设计原则,他指导我们如何创建一个稳定的、灵活的系统
此时有一个需求书店打9折促销,面对需求变化,我们一般有三种解决办法:
1.修改接口(不可行)
2.修改实现类(不是最优)
3.通过拓展实现变化(好办法):增加一个子类去重写getPrince方法,通过这个拓展类来产生新的对象,实现业务变化对系统的最小化开发
变化的三种类型:
1.逻辑变化(只变化一个逻辑,而不涉及其他模块)
2.子模块变化(一个模块变化,会对其他的模块产生影响)
3.可见视图变化(如jsp程序、Swing界面)
开闭原则规范:
1.抽象规范:a.通过接口或者抽象类进行约束拓展,对拓展进行边界限定,不允许出现在接口或抽象类不存在的public方法;b.参数类型、引用对象尽量使用接口或者抽象类,而不是具体实现类;c.抽象类要保持稳定,一旦确定即不允许更改
2.使用元数据控制模块行为:
元数据:用来描述环境和数据的数据,通俗地来讲就是配置参数,参数可以从文件中得,也可以从数据库中获得。
一句话“约定大于配置,配置大于代码”,约定:就是各种约束文件;配置:就是各种xml文件配置;代码:手敲的代码
3.制定项目章程
4.封装变化:a.将相同的变化封装当一个接口或者抽象类中;b.将不同的变化封装到不同的接口或者抽象类中,不应该有两个不同的变化出现在同一接口或者抽象类中(类似手机:不同的品牌,不同的厂商....)