编码依据的准则——七大设计原则(上)

这是我参与新手入门的第3篇文章编程

简述

咱们总想写出正确的代码,而设计原则就是咱们写出正确代码可依据的准则。由于,原则是通过长期经验总结所得出的合理化的现象。设计模式

咱们经常使用的七大设计原则(也称为设计模式的七大原则或面向对象的七大设计原则):markdown

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

通常地,能够把这七个原则分红了如下两个部分:ide

设计方法:单一职责原则、接口分隔原则、依赖倒置原则、组合/聚合复用原则编码

设计目标:开闭原则、里氏代换原则、迪米特原则spa

这篇文章先聊聊「设计方法」相关的原则。设计

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

顾名思义,单一职责原则就是一个类/接口/方法有且仅有一个职责。code

更官方的说法是,单一职责原则规定一个类应该有且仅有一个引发它变化的缘由,不然类应该被拆分(There should never be more than one reason for a class to change)。 能够这样理解,若是类职责不「单一」,每一个职责的变化都有各自的缘由。orm

单一职责原则的核心就是控制类的粒度大小、将对象解耦、提升其内聚性对象

遵循单一职责原则有如下优势:

  1. 下降类的复杂度。一个类只负责一项职责,其逻辑确定要比负责多项职责简单得多。
  2. 提升类的可读性。当类遵循单一职责时,你天然很容易知道此类是干什么的。
  3. 增长可复用性。若是一个方法是多个职责的,你只想使用其中的一个职责,这个方法就是不可复用的。好比,修改用户信息。用户信息有用户名,信息,密码,家庭地址等等。若是你把全部的信息修改放到一个方法中,那么修改密码功能就不能复用这个方法了。
  4. 下降变动引发的风险。当一个类有多个职责时,你改变其中一个职责,就有可能影响其余职责。

接口分隔原则 (Interface Segregation Principle, ISP)

概念理解:接口的设计应该遵循最小接口原则,即不能强迫用户去依赖那些他们不使用的接口。

好比,接口A,定义了三个方法:

public interface A {
    
    void method1();
    
    void method2();
    
    void method3();
}
复制代码

而类B,只依赖A的两个方法:

public class B implements A{
    @Override
    public void method1() {
        System.out.println("do method 1");
    }

    @Override
    public void method2() {
        System.out.println("do method 2");
    }

    @Override
    public void method3() {
        // do nothing
    }
}
复制代码

这样,A接口就是没有遵循最小接口原则。按接口分隔原则,就应该将接口拆分红使B类不会依赖那些他们不使用的接口。

// 将接口A拆成A1和A2
public interface A1 {
    
    void method1();
    
    void method2();
}

public interface A2 {
    
    void method3();
}

// B只须要依赖A1
public class B implements A1{
    @Override
    public void method1() {
        System.out.println("do method 1");
    }

    @Override
    public void method2() {
        System.out.println("do method 2");
    }
}

复制代码

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

依赖倒置原则定义

A. 上层模块不该该依赖底层模块,它们都应该依赖于抽象(High level modules should not depend upon low level modules. Both should depend upon abstractions)

B. 抽象不该该依赖于细节,细节应该依赖于抽象(Abstractions should not depend upon details. Details should depend upon abstractions)

什么是底层模块?咱们能够把不可分隔的逻辑(最基础的方法)当成底层模块,而组装或使用他们的逻辑就是上层模块。「上层模块和底层模块都应该依赖于抽象」,能够用代码这样理解:

示例1(不遵循依赖倒置原则):

// 底层模块
public class LowLevel{
    public void methodLow(){
        System.out.println("底层方法");
    }
}

// 上层模块,直接依赖底层模块
public class HighLevel {
    public void methodHigh(LowLevel lowLevel) {
        System.out.println("上层模块");
        lowLevel.methodLow();
    }
}
复制代码

示例2(遵循依赖倒置原则)

// 抽象接口
public interface AbstractLevel {
    void method();
}

// 底层模块依赖抽象
public class LowLevel implements AbstractLevel{
    @Override
    public void method(){
        System.out.println("底层方法");
    }
}

// 上层模块依赖抽象
public class HighLevel {
    public void methodHigh(AbstractLevel abstractLevel) {
        System.out.println("上层模块");
        abstractLevel.method();
    }
}
复制代码

依赖倒转(倒置)的中心思想就是针对接口编程,不要针对实现编程

组合/聚合复用原则 (Composite/Aggregate Reuse Principle, CARP)

组合/聚合复用原则定义:

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

简单来讲就是多用组合,少用继承。

在面向对象设计中,有两种基本的办法能够实现复用:第一种是经过组合/聚合,第二种就是经过继承。而两种方式以「Has-A」(组合)和「Is-A」(继承)区分。

直接继承基类,会破坏封装,由于继承将基类的实现细节暴露给子类;若是基类的实现发生了改变,则子类的实现也不得不改变。

小结

本篇文章主要介绍了「单一职责原则」、「接口分隔原则」、「依赖倒置原则」、「组合/聚合复用原则」,这些原则能够理解为咱们编码所遵循的方法。而下一篇文章,咱们会介绍「开闭原则」、「里氏代换原则」、「迪米特原则」,这三个原则是咱们编码所要实现的目标。

相关文章
相关标签/搜索