设计模式(Design Patterns)
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
运用设计模式要遵守一定的原则。
1、OCP(Open Close Principle)开-闭原则
OCP是Java里最基础的设计原则,它指导我们建立一个健壮的,灵活的系统。
概念:一个软件实体如类、模块或者函数应该对扩展开放,对修改关闭。开闭原则的含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有代码来实现变化。
注意:开闭原则对扩展开放,对修改关闭,并不意味着不做任何修改,低层模块的变更,必然要有高层模块进行耦合,否则就是一个孤立无意义的代码片段了。
重要性:对测试的影响(只需要测试扩展代码);提高可维护性与复用性;面向对象开发的要求。
使用:抽象约束;元数据(metadata 通常来说就是配置参数)控制模块行为;制定项目章程;封装变化
2、迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle,LKP)
概念:一个对象应该对其他对象有最少的了解。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的public方法,我就调用这么多,其他的一概不关心。通俗含义就是不和陌生人说话|朋友间也是有距离的|自己的就是自己的|谨慎使用Serializable。
核心观念就是类间解耦
3、接口隔离原则 (Interface Segregation Principle , ISP)
定义:客户端不应该依赖它不需要的接口;类间的依赖关系应该建立在最小的接口上。
含义:
- 接口要尽量小(核心),必须满足单一职责原则。
- 接口要高内聚(接口中尽量少公布public方法)
- 定制服务(单独为一个个体提供优良的服务。)
- 接口设计是有限度的
4、依赖倒置原则(Dependence Inversion Principle,DIP)
定义:
- 高层模块不应该依赖底层模块,两者都应该依赖其抽象;
- 抽象不应该依赖细节;
- 细节应该依赖抽象。
JAVA中的表现
- 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或者抽象类产生的;
- 接口或抽象类不依赖于实现类;
- 实现类依赖接口或抽象类。
“面向接口编程”
采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。
本质
:依赖倒置原则的本质就是通过抽象(接口或者抽象类)使各个类或模型的实现彼此独立,不互相影响,实现模块间的松耦合。
规则:
- 每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备;
- 变量的表面类型尽量是接口或者抽象类;
- 任何类都不应该从具体类派生;
- 尽量不要覆写基类的方法;
- 结合里氏替换原则使用。
- 接口负责定义public属性和方法,并且声明与其他对象的依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑,同时在适当的时候对父类进行细化。
依赖倒置与依赖正置
依赖正置就是类间的依赖是实实在在的实现类间的依赖,也就是面向实现编程,这也是正常人的思维方式,我要开奔驰车就依赖奔驰车,我要使用笔记本电脑就直接依赖笔记本电脑,而编写程序需要的是对现实世界的事物进行抽象,抽象的结构就是有了抽象类和接口,然后我们根据系统设计的需要产生了抽象间的依赖,代替了人们传统思维中的事物间的依赖,“倒置”就是从这里产生的。
5、里氏替换原则(Liskov Substitution Principel,LSP)
里氏替换原则(Liskov Substitution Principel)是解决继承带来的问题。
关于继承
**继承的优点**:
- 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
- 提高代码的重用性;
- 子类可以形似父类,但又异于父类;
- 提高代码的可扩展性;
- 提高产品或项目的开放性。
**继承的缺点:**
- 继承是侵入性的,只要继承就必须拥有父类的所有属性和方法;
- 降低代码的灵活性,子类必须拥有父类的属性和方法,让子类增加了约束;
- 增强了耦合性,当父类的常量、变量和方法被修改时,必须考虑子类的修改。
(LSP)定义
所有引用基类的地方必须能透明地使用其子类的对象。
通俗点讲,只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行了,有子类出现的地方,父类未必就能适应。
含义
- 子类必须完全实现父类的方法
- 子类可以有自己的个性
- 覆盖或实现父类的方法时输入参数可以被放大
- 覆盖或实现父类的方法时输出结果可以被缩小
目的:
采用里氏替换原则的目的就是增强程序的健壮性,版本升级是也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑。
6、单一职责原则(SRP)
定义:
应该有且仅有一个原因引起类的变更。
There should never be more than one reason for a class to change.
优点:
- 1、类的复杂性降低,实现什么职责都有清晰明确的定义;
- 2、可读性提高,复杂性减低,可读性当然提高;
- 3、可维护性提高,可读性提高,可维护性当然提高;
- 4、变更引起的风险减低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的类有影响,对其他接口无影响,这对系统的扩展性、维护性都有非常大的帮助。
注意:
单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否优良,但是“职责”和“变化原因”都是不可度量的,因项目而异,因环境而异。
建议:
接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。
参考文献