设计模式之单一职责原则

定义:不要存在多于一个导致类变更的原因。通俗地说,即一个类只负责一项职责。

问题由来:类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能导致原本运行正常的职责P2功能发生故障。

解决方案:遵循单一职责原则。分别建立两个类T1、T2。这样修改时互不影响。

很多人会认为这原则太简单了,但即使是经验丰富的程序员写出的程序,也有违背这一原则的代码存在。为什么会有这一现象呢?因为有职责扩散。所谓职责扩散,就是因为某种原因,职责P被分化为粒度更细的职责P1和P2。这时负责该P职责的T类页分解为两个类T1和T2,分别负责P1、P2两个职责。但这样太浪费时间了,所以简单修改类T,用它来负责两个职责是个不错的选择,虽然这违背了单一职责原则。这样做的风险在于职责扩散的不确定性,有可能扩散为P1,P2,P3,,,Pn。所以在无法控制之前,立刻对代码进行重构。

举例说明,用一个类描述动物呼吸这个场景:

class Animal {

  public void breathe(String animal){

    System.out.println(animal + "呼吸空气");

  }

}

public class Client {

  public static void main(String[] args){

    Animal animal = new Animal();

    animal.breathe("牛");

    animal.breathe("羊");

    animal.breathe("猪");

  }

}

程序上线后,发现了问题,并不是所以的动物都是呼吸空气的,比如鱼就是吸水的。修改时如果遵循单一职责原则,需要将Animal类细分为陆生动物类Terrestrial,水生动物Aquatic:

class Terrestrial{

  public void breathe(String animal){

    System.out.println(animal + "呼吸空气");

  }

}

class Aquatic{

  public void breathe(String animal){

    System.out.println(animal + "呼吸水");

  }

}

public class Client {

  public static void main(String[] args){

    Terrestrial animal = new Terrestrial();

    animal.breathe("牛");

    animal.breathe("羊");

    animal.breathe("猪");

    Aquatic animal2 = new Aquatic();

    animal2.breathe("鱼");

  }

}

我们发现这样修改花销是很大的,除了将原来的类分解之外,还需要修改客户端。而直接修改类Animal来达成目的虽然违背了单一职责原则,但花销却小很多。

class Animal {

  public void breathe(String animal) {

    if("鱼".equals(animal)){

      System.out.println(animal + "呼吸水");

    }else {

      System.out.println(animal + "呼吸空气");

    }

  }

}

可以看到这种修改方式要简单很多,但存在隐患:有一天需要将鱼分为呼吸淡水的鱼和呼吸海水的鱼,则又需要修改Animal类的breathe方法,给原有功能带来风险,隐患很大。

还有一种修改方法:

class Animal {

  public void breathe(String animal){

    System.out.println(animal + "呼吸空气");

  }

  public void breathe2(String animal){

    System.out.println(animal + "呼吸水");

  }

}

可以看到这种方法没有改变原来的方法,这样虽然违背了单一职责原则,但在方法级别上却是符合单一职责原则的。这三种方法各有优缺点,那到底选哪种呢?我的原则:只有逻辑足够简单,才可以在代码级别上违反单一职责原则;只有类中的方法数量足够少,才可以在方法级别上违背单一职责原则。

遵循单一职责原则优点:

可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定比负责多项职责的简单的多;

提高类的可读性,提高系统的可维护性;

降低变更引起的风险。

(本文内容来自“java利器”app)

猜你喜欢

转载自www.cnblogs.com/shicaiyou/p/9203443.html