开闭原则
对扩展开放,对修改关闭
例子
其中AbstractSkin
是抽象类,皮肤类:
package com.linghu.demo01; /** * 抽象皮肤类 * @author linghu * @date 2024/2/1 15:42 */ public abstract class AbstractSkin { //展示皮肤的方法 public abstract void display(); }
另外的DefaultSpecificSkin
、HeimaSpecificSkin
、SouGouInput
三个是子类,不动这三个子类的情况下,自己新建皮肤类,然后在下面代码【2】处进行更改,实现良好的扩展性。
Test
类如下:
package com.linghu.demo01; /** * @author linghu * @date 2024/2/1 15:58 */ public class Client { public static void main(String[] args) { //1、创建搜狗输入法对象 SouGouInput input = new SouGouInput(); //2、创建皮肤对象 HeimaSpecificSkin skin = new HeimaSpecificSkin(); // DefaultSpecificSkin skin = new DefaultSpecificSkin(); //3、将皮肤设置到输入法中 input.setSkin(skin); //4、显示皮肤 input.display(); } }
总结
对扩展开放,对修改关闭的含义就是: 我们可以在定义扩展其他皮肤类【2】,只要在上述代码中新建对象即可。不需要修改原有的DefaultSpecificSkin
、HeimaSpecificSkin
、SouGouInput
三个子类。
里氏代换原则
子类可以扩展父类的功能,但不能改变父类原有的功能。换句话说,子类继承父类时,除了添加新的方法完成额外功能外,尽量不要重写父类的方法。
基本介绍
- 里氏替换原则在1988年,有麻省理工学院的以为姓里的女士提出的。
- 如果对每个类型为T1的对象o1,都有类型为T2的对象o2,使得T1定义的所有的对象o1都替换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。换句话说,所欲引用基类的地方必须能透明的使用其子类的对象。
- 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法。
- 继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖来解决问题
例子
为遵循里氏替换原则的后果:
package com.weirdo.principle.liskov; public class Liskov { public static void main(String[] args) { A a = new A(); System.out.println("11-3="+a.func1(11,3)); System.err.println("=========================="); B b = new B(); //这里本意求11-3 System.out.println("11-3="+b.func1(11,3)); System.out.println("1-8="+b.func1(1,8)); System.out.println("11+3+1="+b.func2(11,3)); } } //A类 class A { //返回两个数的差 public int func1(int num1, int num2) { return num1 - num2; } } //B类继承了A //增加了一个新功能:完成两个数相加,然后和1求和 class B extends A { //这里,重写了A类的方法,可能是无意识 public int func1(int a, int b) { return a + b; } public int func2(int a, int b) { return a + b + 1; } }
依赖倒转原则
基本介绍
高层模块不应该依赖底层模块,两者都应该依赖其抽象;这里的抽象就是指:接口! 抽象不应该依赖细节,细节应该依赖抽象,简单地说就是要求对抽象(接口)进行编程,不要对实现进行编程,这样就降低了客户与实现模块之间的耦合。
例子
如下图所示,扩充的IntelCpu
类没法更换成其他的CPU类,就很不方便
在这个Computer
类中,如果我们要添加一个CPU的话,就要修改Computer
类,这就会导致臃肿麻烦。违背了开闭原则!
接下来使用依赖倒转原则,就是把类抽取出接口:
如上做的好处就是,如果有其他品牌的CPU加入,我们只需要在实现类旁边进行扩充,去实现接口即可!
接口隔离原则
基本介绍
**客户端不应该被迫依赖于它不使用的方法;一个类对另一个类的依赖应该建立在最小的接口上。 **
例子
上面的代码设计如下图:
这种设计的缺陷在于,黑马品牌的安全门具有防盗,防水,防火的功能。现在如果我们还需要再创建一个传智品牌的安全门,而该安全门只具有防盗、防水功能呢?很显然如果实现SafetyDoor接口就违背了接口隔离原则,那么我们如何进行修改呢?看如下类图:
改进以后的代码:
package com.linghu.demo04.after; /** * 新品牌门的加入 * @author linghu * @date 2024/2/4 9:57 */ public class NewDoor implements AntiTheft,Fireproof{ @Override public void antiTheft() { System.out.println("防盗"); } @Override public void fireproof() { System.out.println("防火"); } }
新品牌的门的加入就不会在影响之前的门的牌子类了。这就是接口隔离的好处。
迪米特法则
基本介绍
**其实就是类似于Java中的代理,或者直接点就是外包公司!。**主打的是一种办事情的流程,这种方便的流程。
为什么要找软件公司呢?这个外包公司可以帮助程序员和客户省去交流的成本,沟通的成本,提高效率!
24种设计模式详解(下)+https://developer.aliyun.com/article/1625050