单一职责原则

单一职责原则:一个类只负责一个功能领域中的相应职责。或者说,就一个类而言,应该只有一个引起它变化的原因。

单一职责原则告诉我们:一个类不能太“累”!在软件系统中,一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中。

示例

class CustomerDataChart{
  getConnection(){}
  findCustomers(){}
  createChart(){}
  displayChart(){}
}

CustomerDataChart类中的方法说明如下:getConnection()方法用于获取数据,findCustomers()用于查询所有的客户信息,createChart()用于创建图表,displayChart()用于显示图表。

CustomerDataChart类承担了太多的职责,既包含与数据库相关的方法,又包含与图表生成和显示相关的方法。因此需要对该类进行拆分,使其满足单一职责原则,类CustomerDataChart可拆分为如下三个类:

  • DataUtil:负责获取数据,包含获取数据方法getConnection();
  • CustomerHandle:负责查询客户信息,包含方法findCustomers();
  • CustomerDataChart:负责图表的生成和显示,包含方法createChart()和displayChart()。
class DataUtil{
  getConnection(){}
}

class CustomerHandle{
  findCustomers(){}
}

class CustomerDataChart{
  createChart(){}
  displayChart(){}
}

开闭原则

开闭原则:一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

示例

class ChartDisplay{
  display(type){
    if ( type == "pie" ) {  
      let chart = new PieChart();  
      chart.display();  
    } else if ( type =="bar" ) {  
      let chart = new BarChart();  
      chart.display();  
    }  
  }
}

class PieChart{
  display(){
    console.log('show Pie')
  }
}

class BarChart{
  display(){
    console.log('show Bar')
  }
}

在该代码中,如果需要增加一个新的图表类,如折线图 LineChart,则需要修改ChartDisplay类的display()方法的源代码,增加新的判断逻辑,原则告诉我们要对修改关闭,所以这份代码违反了开闭原则。

可以通过抽象化的方式对系统进行重构,使之增加新的图表类时无须修改源代码,满足开闭原则。做法如下:

  • 增加一个抽象图表类AbstractChart,将各种具体图表类作为其子类
  • ChartDisplay类针对抽象图表类进行编程,由客户端来决定使用哪种具体图表
class ChartDisplay{
  constructor(abstractchart){
    this.chart = abstractchart
  }
  display(){
    this.chart.display();  
  }
}

class AbstractChart{
  display(){
    throw new Error("This method must be overwritten!");
  }
}

class PieChart extends AbstractChart{
  display(){
    console.log('show Pie')
  }
}

class BarChart extends AbstractChart{
  display(){
    console.log('show Bar')
  }
}

// 测试一下
let chart = new ChartDisplay( new PieChart() );
chart.display();

若此时需要用到折线图功能,仅需扩展一个 LineChart 类,将 LineChart 也作为 AbstractChart 的子类即可,且无需修改其他类库代码。这种对扩展开放,对修改封闭就是属于开闭原则。

class LineChart extends AbstractChart{
  display(){
    console.log('show Line')
  }
}

// 测试以下
let chart = new ChartDisplay( new LineChart() );
chart.display();

里氏代换原则

里氏代换原则:所有引用基类(父类)的地方必须能透明地使用其子类的对象。

里氏代换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。例如:我喜欢动物,那我一定喜欢狗,因为狗是动物的子类;但是我喜欢狗,不能据此断定我喜欢动物,因为我并不喜欢老鼠,虽然它也是动物。

依赖倒转原则

依赖倒转原则:抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。

隔离原则

接口隔离原则:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。

合成复用原则

合成复用原则:尽量使用对象组合,而不是继承来达到复用的目的。

迪米特法则,又称最少知道原则

迪米特法则:一个软件实体应当尽可能少地与其他实体发生相互作用。

如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易。迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。

results matching ""

    No results matching ""