设计模式的基本原则

  1. 单一职责原则 (Single Responsibility Principle)
  2. 开放-关闭原则 (Open-Closed Principle)
  3. 里氏替换原则 (Liskov Substitution Principle)
  4. 依赖倒转原则 (Dependence Inversion Principle)
  5. 接口隔离原则 (Interface Segregation Principle)
  6. 迪米特法则(Law Of Demeter)
  7. 组合/聚合复用原则 (Composite/Aggregate Reuse Principle)

1.单一职责原则 SRP(Single Responsibility Principle)

就一个类而言,应该仅有一个让它变化的原因;通俗地说,即一个类只负责一项职责。

  1. SRP 是一个简单又直观的原则,但是在实际编码的过程中很难将它恰当地运用,需要结合实际情况进行运用。
  2. 单一职责原则可以降低类的复杂度,一个类仅负责一项职责,其逻辑肯定要比负责多项职责简单。
  3. 提高了代码的可读性,提高系统的可维护性。

2. 开放-关闭原则 OCP (Open-Closed Principle)

软件实体 (类、模块、函数等等) 对扩展开放,对修改关闭

如果一个软件能够满足 OCP 原则,那么它将有两项优点:

  1. 能够扩展已存在的系统,能够提供新的功能满足新的需求,因此该软件有着很强的适应性和灵活性。
  2. 已存在的模块,特别是那些重要的抽象模块,不需要被修改,那么该软件就有很强的稳定性和持久性。

3. 里氏替换原则 LSP(Liskov Substitution Principle)

里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能(如果改变了,父类可能就没有存在的必要了)

里氏替换原则的重点在不影响原功能,而不是不覆盖原方法。

4. 依赖倒转原则 DIP (Dependence Inversion Principle)

高层模块不应该依赖低层模块,二者都应该依赖于抽象。进一步说,抽象不应该依赖于细节,细节应该依赖于抽象。

依赖倒转原则的核心思想就是面向接口编程

5. 接口隔离原则 ISP (Interface Segregation Principle)

接口隔离原则强调:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。

 

这个图的意思是:类A依赖接口I中的方法1、方法2、方法3,类B是对类A依赖的实现。类C依赖接口I中的方法1、方法4、方法5,类D是对类C依赖的实现。对于类B和类D来说,虽然他们都存在着用不到的方法(也就是图中红色字体标记的方法),但由于实现了接口I,所以也必须要实现这些用不到的方法。

用代码表示:

interface I {  
    public void method1();  
    public void method2();  
    public void method3();  
    public void method4();  
    public void method5();  
}  
  
class A{  
    public void depend1(I i){  
        i.method1();  
    }  
    public void depend2(I i){  
        i.method2();  
    }  
    public void depend3(I i){  
        i.method3();  
    }  
}  
  
class B implements I{  
	 // 类 B 只需要实现方法 1,2, 3,而其它方法它并不需要,但是也需要实现
    public void method1() {  
        System.out.println("类 B 实现接口 I 的方法 1");  
    }  
    public void method2() {  
        System.out.println("类 B 实现接口 I 的方法 2");  
    }  
    public void method3() {  
        System.out.println("类 B 实现接口 I 的方法 3");  
    }  
    public void method4() {}  
    public void method5() {}  
}  
  
class C{  
    public void depend1(I i){  
        i.method1();  
    }  
    public void depend2(I i){  
        i.method4();  
    }  
    public void depend3(I i){  
        i.method5();  
    }  
}  


class D implements I{  
	// 类 D 只需要实现方法 1,4,5,而其它方法它并不需要,但是也需要实现
    public void method1() {  
        System.out.println("类 D 实现接口 I 的方法 1");  
    }  
    public void method2() {}  
    public void method3() {}  
    public void method4() {  
        System.out.println("类 D 实现接口 I 的方法 4");  
    }  
    public void method5() {  
        System.out.println("类 D 实现接口 I 的方法 5");  
    }  
}  
  
public class Client{  
    public static void main(String[] args){  
        A a = new A();  
        a.depend1(new B());  
        a.depend2(new B());  
        a.depend3(new B());  
          
        C c = new C();  
        c.depend1(new D());  
        c.depend2(new D());  
        c.depend3(new D());  
    }  
}  

  可以看出,如果接口定义的过于臃肿,只要接口中出现的方法,不管依赖于它的类是否需要该方法,实现类都必须去实现这些方法,这就不符合接口隔离原则,如果想符合接口隔离原则,就必须对接口 I 如下图进行拆分:

 

 代码可修改为如下:

interface I1 {  
    public void method1();  
}  
  
interface I2 {  
    public void method2();  
    public void method3();  
}  
  
interface I3 {  
    public void method4();  
    public void method5();  
}  
  
class A{  
    public void depend1(I1 i){  
        i.method1();  
    }  
    public void depend2(I2 i){  
        i.method2();  
    }  
    public void depend3(I2 i){  
        i.method3();  
    }  
}  
  
class B implements I1, I2{  
    public void method1() {  
        System.out.println("类 B 实现接口 I1 的方法 1");  
    }  
    public void method2() {  
        System.out.println("类 B 实现接口 I2 的方法 2");  
    }  
    public void method3() {  
        System.out.println("类 B 实现接口 I2 的方法 3");  
    }  
}  
  
class C{  
    public void depend1(I1 i){  
        i.method1();  
    }  
    public void depend2(I3 i){  
        i.method4();  
    }  
    public void depend3(I3 i){  
        i.method5();  
    }  
}  
  
class D implements I1, I3{  
    public void method1() {  
        System.out.println("类 D 实现接口 I1 的方法 1");  
    }  
    public void method4() {  
        System.out.println("类 D 实现接口 I3 的方法 4");  
    }  
    public void method5() {  
        System.out.println("类 D 实现接口 I3 的方法 5");  
    }  
}  

  

  1. 接口隔离原则的思想在于建立单一接口,尽可能地去细化接口,接口中的方法尽可能少
  2. 但是凡事都要有个度,如果接口设计过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。

6. 迪米特法则 LOD(Law Of Demeter),又称最少知道原则

它表示一个对象应该对其它对象保持最少的了解。通俗来说就是,只与直接的朋友通信。

首先来解释一下什么是直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。

对于被依赖的类来说,无论逻辑多么复杂,都尽量的将逻辑封装在类的内部,对外提供 public 方法,不对泄漏任何信息。

7. 组合/聚合复用原则 CRP(Composite/Aggregate Reuse Principle)

组合/聚合复用原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分; 新的对象通过向这些对象的委派达到复用已有功能的目的。

在面向对象的设计中,如果直接继承基类,会破坏封装,因为继承将基类的实现细节暴露给子类;如果基类的实现发生了改变,则子类的实现也不得不改变;从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性。于是就提出了组合/聚合复用原则,也就是在实际开发设计中,尽量使用组合/聚合,不要使用类继承。

  1. 总体说来,组合/聚合复用原则告诉我们:组合或者聚合好过于继承。
  2. 聚合组合是一种 “黑箱” 复用,因为细节对象的内容对客户端来说是不可见的。
posted @ 2021-03-04 19:58  455994206  阅读(23)  评论(0)    收藏  举报