乐趣区

关于设计原则:设计模式原则之单一职责原则SRP

人生没有白走的路,每一步都算数

前言

在面向对象的软件设计中,只有尽量升高各个模块之间的耦合度,能力进步代码的复用率,零碎的可维护性、可扩展性能力进步。面向对象的软件设计中,有 23 种经典的设计模式,是一套前人代码设计教训的总结,如果把设计模式比作文治招式,那么设计准则就好比是内功心法。罕用的设计准则有七个,本文将具体介绍繁多职责准则。

设计准则简介

  • 繁多职责准则:专一升高类的复杂度,实现类要职责繁多;
  • 凋谢敞开准则:所有面向对象准则的外围,设计要对扩大开发,对批改敞开;
  • 里式替换准则:实现凋谢敞开准则的重要形式之一,设计不要毁坏继承关系;
  • 依赖倒置准则:零碎抽象化的具体实现,要求面向接口编程,是面向对象设计的次要实现机制之一;
  • 接口隔离准则:要求接口的办法尽量少,接口尽量细化;
  • 迪米特法令:升高零碎的耦合度,使一个模块的批改尽量少的影响其余模块,扩大会绝对容易;
  • 组合复用准则:在软件设计中,尽量应用组合 / 聚合而不是继承达到代码复用的目标。

这些设计准则并不说咱们肯定要遵循他们来进行设计,而是依据咱们的理论状况去怎么去抉择应用他们,来让咱们的程序做的更加的欠缺。

繁多职责准则

就一个类而言,应该仅有一个引起它变动的起因,艰深的说,就是一个类只负责一项职责。此准则的外围就是解耦和加强内聚性。

如果一个类承当的职责过多,就等于把这些职责耦合在一起,一个职责的变动可能会减弱或者克制这个类实现其余职责的能力。这种耦合会导致软弱的设计。

长处

(1)升高类的复杂度;

(2)进步类的可读性,进步零碎的可维护性;

(3)升高变更引起的危险(升高对其余性能的影响)。

咱们来举一些简略的例子来阐明一下这个繁多职责准则

public class Animal {public void breathe(String animal) {System.out.println(animal + "生存在海洋上");
    }
}

public class Test {public static void main(String[] args) {Animal animal = new Animal();
        animal.breathe("牛");
        animal.breathe("羊");
    }
}

运行后果:

 牛生存在海洋上
羊生存在海洋上 

动物并不是都生存在海洋上的,鱼就是生存在水中的,批改时如果遵循繁多职责准则,须要将 Animal 类细分为陆生动物类 Land,水生动物 Water,代码如下:

public class Land {public void breathe(String animal) {System.out.println(animal + "生存在海洋上");
    }
}

public class Water {public void breathe(String animal) {System.out.println(animal + "生存在水里");
    }
}

public class Test {public static void main(String[] args) {Land land = new Land();
        land.breathe("牛");
        land.breathe("马");
        Water water = new Water();
        water.breathe("鱼");
    }
}

运行后果:

 牛生存在海洋上
马生存在海洋上
鱼生存在水里 

然而问题来了如果这样批改花销是很大的,除了将原来的类合成之外,还须要批改客户端。而间接批改类 Animal 来达成目标尽管违反了繁多职责准则,但花销却小的多,代码如下:

public class Animal {public void breathe(String animal) {if ("鱼".equals(animal)) {System.out.println(animal + "生存在水里");
        }
        System.out.println(animal + "生存在海洋上");
    }
}

public class Test {public static void main(String[] args) {Animal animal = new Animal();
        animal.breathe("牛");
        animal.breathe("羊");
        animal.breathe("鱼");
    }
}

运行后果:

 牛生存在海洋上
马生存在海洋上
鱼生存在水里 

能够看到,这种批改形式要简略的多。然而却存在着隐患:有一天须要将鱼分为生存在咸水中的鱼和生存在淡水的鱼,则又须要批改 Animal 类的 breathe 办法,而对原有代码的批改会对调用“猪”“牛”“羊”等相干性能带来危险。

这种批改形式间接在代码级别上违反了繁多职责准则,尽管批改起来最简略,但隐患却是最大的。还有一种批改形式:

public class Animal {public void breathe(String animal) {System.out.println(animal + "生存在海洋上");
    }

    public void breathe1(String animal) {System.out.println(animal + "生存在水里");
    }
}

public class Test {public static void main(String[] args) {Animal animal = new Animal();
        animal.breathe("牛");
        animal.breathe("羊");
        animal.breathe1("鱼");
    }
}

运行后果:

 牛生存在海洋上
马生存在海洋上
鱼生存在水里 

能够看到,这种批改形式没有改变原来的办法,而是在类中新加了一个办法,这样尽管也违反了繁多职责准则,但在办法级别上却是合乎繁多职责准则的,因为它并没有动原来办法的代码。

总结

以上通过一个利用场景简略介绍了下繁多职责准则的应用,下面三种设计,没有最正当,只有最合适。

这三种形式各有优缺点,那么在理论编程中,采纳哪一中呢?其实这真的比拟难说,须要依据理论状况来确定。

例如本文所举的这个例子,它太简略了,它只有一个办法,所以,无论是在代码级别上违反繁多职责准则,还是在办法级别上违反,都不会造成太大的影响。理论利用中的类都要简单的多,一旦产生职责扩散而须要批改类时,除非这个类自身非常简单,否则还是遵循繁多职责准则的好。

了解繁多职责准则,最重要的就是了解职责的划分,职责划分的粒度取决于需要的粒度。

退出移动版