设计模式之设计模式的七大原则
一、走进设计模式
1.设计模式的概念
软件设计模式(Software Design Pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。其目的是为了提高代码的可重用性、代码的可读性和代码的可靠性。
2.设计模式的分类
2.1 创建型模式
单例模式,抽象工厂模式,工厂方法模式,原型模式,建造者模式
2.2 结构型模式
适配器模式,桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式
2.3 行为型模式
模板方法模式,命令模式,访问者模式,迭代器模式,观察者模式,中介者模式,备忘录模式,解释器模式,状态模式,策略模式,职责链模式
二、设计模式七大原则
1.单一职责原则
- 单一职责原则(Single Responsibility Principle,SRP),单一职责原则规定一个类或接口应该有且仅有一个引起它变化的原因,否则类应该被拆分。即一个类或接口只负责一个功能领域中的相应职责。
- 如类A负责两个不同职责:职责1,职责2。当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为 A1,A2。
public interface Dao {
//获取一个User
User getUserByName(String name);
//获取User集合
List<User> getUserList();
//获取一个订单
Order getOrderById(String id);
}
- 由于人为的不规范,将操作Order的操作与操作User的操作放到了同一个Dao中,这就没有遵守单一职责原则
2.开闭原则
-
开闭原则(Open Closed Principle,OCP)定义:一个软件实体(如类、模块和函数)应该对扩展开放(对提供方),对修改关闭(对使用方)。 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
-
开闭原则是编程中最基础、最重要的设计原则
-
编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。
-
Arithmetic是一个抽象类,能够进行运算,但是并没有指定是什么运算。有两个子类继承Arithmetic,一个加法类,一个减法类。现在需要扩展功能,添加乘法类和除法类。此时对于测试类(使用方)来说,无需修改任何东西,可直接进行测试。而对于提供方可随意进行扩展。
3.里氏替换原则
- 里氏替换原则(Liskov Substitution Principle)在1988年,由麻省理工学院的一位姓里的女士提出的。
- 里氏替换原则主要阐述了有关继承的一些原则,也就是什么时候应该使用继承,什么时候不应该使用继承,以及其中蕴含的原理。里氏替换原则是对开闭原则的补充,是对实现抽象化的具体步骤的规范。
- 里氏替换原则通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。
- 里氏替换原则告诉我们,继承实际上让两个类耦合性增强了。在适当的情况下,可以使原来的父类和子类都继承一个更通俗的基类,去掉原来的继承关系,使用聚合,组合,依赖来代替继承关系。
4.依赖倒转(倒置)原则
- 依赖倒转原则(Dependence Inversion Principle,DIP)的原始定义为:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
- 依赖倒转(倒置)的中心思想是面向接口编程
- 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中,抽象指的是接口或抽象类,细节就是具体的实现类
- 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成
- 继承抽象类时要遵循里氏替换原则
5.接口隔离原则
-
接口隔离原则(Interface Segregation Principle,ISP)要求程序员尽量将臃肿庞大的接口拆分成更小的和更具体的接口。
-
客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上。
-
在一个学生信息管理系统中,有插入成绩、删除成绩、修改成绩、计算总分、计算平均分、查询成绩、打印成绩等功能。如果将这些功能全部放在一个接口中显然不合理,应该将这个大的接口进行拆分,拆分成成绩操作模块、成绩计算模块、成绩打印模块。
6.迪米特法则
- 迪米特法则(Law of Demeter,LoD)又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的public方法,不对外泄露任何信息
- 迪米特法则还有个更简单的定义:只与直接的朋友通信
- 直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。
- 迪米特法则的核心是降低类之间的耦合
- 但是注意:由于每个类都减少了不必要的依赖,因此迪米特法则只是要求降低类间(对象间)耦合关系,并不是要求完全没有依赖关系
- 公司Boss谈成了一单生意,需要团队来做,Boss只需要将相关内容告诉团队leader即可,无需关注团队内部是如何完成的。这就符合了迪米特法则。
7.合成复用原则
- 合成复用原则(Composite Reuse Principle,CRP)又叫组合/聚合复用原则。它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
- 如果要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。
- 是否还记得在MVC三层架构中service层有dao层的实例,Controller层有service层的实例
PS:若文章中有错误的地方,可以再评论区指出,感谢。