设计模式七大原则
设计模式概述
设计模式就是对软件设计过程中存在的普遍问题,所提出的解决方案。能够很好的解决一些常见的问题。
设计模式的最终目的就是:高内聚低耦合
- 代码重用性:相同功能的代码,不需要多次编写
- 代码可读性:编程规范性,便于其他程序员阅读
- 代码可扩展性:当增加新的功能后,对原来功能没有影响
七大原则
一、单一责任原则
顾名思义,我们设计的类尽量负责一项功能,这样不容易造成代码混乱,避免出现一些bug。
反例:
Single类:
public class single{
public static void main(String[] args){
People people = new People;
people.run("老师");
people.run("学生");
people.run("校长");
}
}
People类:
public class People{
void run(String type){
System.out.println(type+"给学生上课");
}
}
这样会造成,不管是老师、学生、校长都会调用这个方法,因为People不止负责了一个功能,所以该设计有问题。
改进
对于上面的例子,我们采用单一职责原则重写一下,将People拆分成三个类,分别是学生、老师、校长。让他们负责各自的功能,使其互相不影响。如果想对学生做限制,那么只需要对学生类进行修改。
优化
或者可以将上面People分为三个方法,每个方法对应不同的人员,将单一职责落在方法层面而不是类层面
优缺点
优点:
- 降低类的复杂度,一个类只负责一个职责
- 提高代码的可读性,逻辑清楚明了
- 降低风险,只修改一个类,并不影响其他类的功能
缺点:
- 代码增多(可以将单一职责落在方法层面进行优化)
二、接口隔离原则
类不应该依赖不需要的接口,接口尽量小颗粒划分、如果将多个方法合并为一个接口,再提供给其他系统使用的时候,就必须实现该接口的所有方法,那些方法是根本不需要的,造成使用者的混淆
![](/qrcode.jpg)
三、依赖倒转原则
- 高层模块不应该依赖底层模块,二者都应该依赖接口或抽象类
- 其核心就是面向接口编程
- 依赖倒转原则主要是基于如下的设计概念:相对于细节的多变性,抽象的东西要更加稳定的多,以抽象为基础搭建的框架更加稳定
- 抽象指接口或抽象类,细节指具体的实现类
反例:
- 设计图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QaVgzavi-1593420283358)(https://raw.githubusercontent.com/iszhonghu/Picture-bed/master/img/20200629150212.png)]
Potato类
public class Potato{
public void run(){
System.out.println("买了土豆");
}
}
People类
public class People{
public void bug(Potato potato){
potato.run();
}
}
Test类
public class Test{
public staticvoid main(String[] args){
People people = People();
people.bug(new Potato());
}
}
改进
上述在反例中,如果不想买土豆,想买其他的蔬菜,就比较麻烦还需要改People方法,这就是代码中的模块和模块之间的耦合性太高。
- 改进后的设计图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QuXNMN0h-1593420283360)(https://raw.githubusercontent.com/iszhonghu/Picture-bed/master/img/20200629150342.png)]
这样我们从底层的类抽象出一个接口类,其直接和高层进行交互,而底层的一些类则不参与,这样能降低耦合度,提高稳定性。
- Vegetables类
public interface Vegetables{
public void run();
}
-
Potato类
public class Potato implements Vegetables{ public void run(){ System.out.println("买了土豆"); } }
-
Tomato类
public class Tomato implements Vegetables{
public void run(){
System.out.println("买了番茄");
}
}
- People类
public class People{
public void bug(Vegetables vegetable){
vegetable.run();
}
}
- Test类
public class Test{
public static void main(String[] args){
People people = new People();
people.bug(new Potato());
people.bug(new Tomato());
}
}
总结
该原则的重点在于”倒转“,要从底层往上思考,尽量抽象抽象类和接口。此例子很好的解释了”上层模型不能依赖底层模块,应该都依赖于抽象“。
四、里氏替换原则
主要是阐述了对继承extend的一些看法
继承的优点:
- 提高代码的可重用性,子类也有父类的属性和方法
- 提高代码的可扩展性,子类有自己特有的方法
继承的缺点:
- 当父类发生改变的时候,要考虑子类的修改
里氏替换原则是继承的基础,只有当子类替换父类时,软件功能仍不受影响,才说明父类真正被复用了。
原则一:
子类必须实现父类的抽象方法,但不得重写(覆盖)父类的非抽象的方法
原则二:
子类中可以增加自己特有的方法。
原则三;
当子类覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更加宽松。
五、开闭原则
前面四个原则都是为了开闭原则做铺垫,其是最基础、最重要的设计原则,核心为对扩展开发,对修改关闭、简单来说,通过扩展软件的行为来实现变化,而不是通过修改来实现。
六、迪米特原则
介绍:
- 一个对象应该对其他对象保持最少的了解。
- 类与类关系越密切,耦合度越大
- 一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的public 方法,不对外泄露任何信息
- 迪米特法则还有个更简单的定义:只与直接(熟悉)的朋友通信
直接(熟悉)的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系, 我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合等。
其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量 的形式出现在类的内部。
七、合成复用原则
- 尽量使用合成/集合,不要用继承
- 如果使用继承,会使得耦合性加强,尽量作为方法的输入参数或类的成员变量,这样可以避免耦合
最后
- 如果觉得看完有收获,希望能给我点个赞,这将会是我更新的最大动力,感谢各位的支持
- 欢迎各位关注我的公众号【java冢狐】,专注于java和计算机基础知识,保证让你看完有所收获,不信你打我
友。也就是说,陌生的类最好不要以局部变量 的形式出现在类的内部。
七、合成复用原则
- 尽量使用合成/集合,不要用继承
- 如果使用继承,会使得耦合性加强,尽量作为方法的输入参数或类的成员变量,这样可以避免耦合
最后
- 如果觉得看完有收获,希望能给我点个赞,这将会是我更新的最大动力,感谢各位的支持
- 欢迎各位关注我的公众号【java冢狐】,专注于java和计算机基础知识,保证让你看完有所收获,不信你打我
- 如果看完有不同的意见或者建议,欢迎多多评论一起交流。感谢各位的支持以及厚爱。