分分28官网|分分28开奖网

实验:设计模式五大原则(1):单一职责原则
作者:强官涛   类型:Java开发    类别:实验   日期:2017-12-08    阅读:2211 次   消耗积分:0 分

单一职责原则(SRP:Single responsibility principle)又称单一功能原则,面向对象五个基本原则(SOLID)之一

定义:不要存在多于一个导致类变更的原因

通俗的说,即一个类只负责一项职责。

问题由来:有类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。也就是说职责P1和P2被耦合在了一起。

解决方案:遵循单一职责原则。分别建立两个类T1、T2,使T1完成职责P1功能,T2完成职责P2功能。这样,当修改类T1时,不会使职责P2发生故障风险;

如果一个类承担的职责过多,就等于把这些职责耦合在一起了。一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当发生变化时,设计会遭受到意想不到的破坏。而如果想要避免这种现象的发生,就要尽可能的遵守单一职责原则。此原则的核心就是解耦和增强内聚性。
没有任何的程序设计人员不清楚应该写出高内聚低耦合的程序,但是很多耦合常常发生在不经意之间,其原因就是:

职责扩散:因为某种原因,某一职责被分化为颗粒度更细的多个职责了。

每一个系统中的功能都表示了一个职责,这些职责可以映射到类中,且应该尽可能的保证这些模块之间没有功能上的重复。设计中每次应只关注一个职责。但这并不是其他的职责都抛之脑后,而是当决定用某个模块来实现某个职责之后,只需全神贯注于该职责相关(核心关注点)。从这个模块的角度出发,其他的职责都是不想关的。

同时模块拥有自己公开的接口,可以和其他模块通信,模块也包含大量内部信息供自身使用。模块中只有接口暴露出的成员才能供其他模块使用。内部数据不是被彻底隐藏,应被筛选后暴露给外部。这样,每个模块仍可以使用固定的接口来通信,而同时不会受到修改具体实现的影响。

举例说明:

public class StudentCadres{
public void manage(String name){
System.out.println(name+"管理班级");
}
}
public class Start{
public static void main(String[] args){
StudentCadres sc = new StudentCadres();
sc.manage("班长");
sc.manage("学习委员");
}
}

运行结果:
班长管理班级
学习委员管理班级

但是并不是所有的学生干部都管理班级,如果将角色增加到学生会干部。
按上述代码完成功能会出现

public class StudentCadres{
public void manage(String name){
System.out.println(name+"管理班级");
}
}
public class Start{
public static void main(String[] args){
StudentCadres sc = new StudentCadres();
sc.manage("班长");
sc.manage("学习委员");
sc.manage("学生会干部");
}
}

运行结果:
班长管理班级
学习委员管理班级
学生会干部管理班级

这显然并不能满足我们的要求,很显然,学生会主席并不会管理班级
自作聪明的程序员将代码修改成了如下方式:

public class StudentCadres{
public void manage(String name){
if(name.equlas("学生会主席")
System.out.println(name+"管理学生会");
else
System.out.println(name+"管理班级");
}
}
public class Start{
public static void main(String[] args){
StudentCadres sc = new StudentCadres();
sc.manage("班长");
sc.manage("学习委员");
sc.manage("学生会干部");
}
}

运行结果:
班长管理班级
学习委员管理班级
学生会干部管理学生会

可以看到,这种修改非常简单,且能适用于目前的需求,但如果职责扩散,我们需要更细的职责粒度,将学生会干部扩散为学生会主席(管理学生会)和宣传干事(负责宣传教育相关事宜)又将如何?你不得不去修改StudentCadres里的manage方法,但修改manange方法时必然对班长和学习委员造成影响。

那么我们是否可以考虑如下的修改形式
public class StudentCadres{

    public void manage(String name){
        System.out.println(name+"管理班级");
    }

    public void manageStudentUnion(String name){
        System.out.println(name+"管理学生会");
    }

    public void propaganda(String name){
        System.out.println(name+"进行宣传");
    }
}
public class Start{
    public static void main(String[] args){
        StudentCadres sc = new StudentCadres();
        sc.manage("班长");
        sc.manage("学习委员");
        sc.manageStudentUnion("学生会主席");
        sc.propaganda("宣传干事");
    }
}

运行结果:
班长管理班级
学习委员管理班级
学生会主席管理学生会
宣传干事进行宣传

上述这种修改方式并没有改动原来的方法,而是在类中新加了两个方法用于表示管理学生会和进行宣传,这样虽然在Class层面上也违背了单一职责原则,但在方法级别上却是符合单一职责原则的,因为该类中每一个方法只完成一个职责,当某一职责发生变更时不会牵涉到其它职责,如果宣传干事罢工或者不负正业干了别的事,我们只需要修改propaganda方法即可,不会对学生会主席、班长、学习委员带来不好的影响;如果新增兴趣小组组长,我们只需要新增方法,也不会影响到学生会主席、班长、学习委员。

在重构的过程中我们也可以严格按照单一职责原则进行重构,那么我们在修改时需在Class层面上就遵循单一职责原则,将学生干部StudentCadres类细分为班干部类ClassCadre,学生会主席类StudentBodyPresident和宣传干事类PropagandaDirector代码如下:
public class ClassCadre{
    public void manage(String name){
        System.out.println(name+"管理班级");
    }
}
public class StudentBodyPresident{
    public void manage(String name){
        System.out.println(name+"管理学生会");
    }
}
public class PropagandaDirector{
    public void manage(String name){
        System.out.println(name+"进行宣传");
    }
}

public class Start{
    public static void main(String[] args){
        ClassCadre cc = new ClassCadre();
        cc.manage("班长");
        cc.manage("学习委员");

        StudentBodyPresident sbp = new StudentBodyPresident();
        sbp.manageStudentUnion("学生会主席");

        PropagandaDirector pd = new PropagandaDirector()
        pd.propaganda("宣传干事");
    }
}

运行结果:
班长管理班级
学习委员管理班级
学生会主席管理学生会
宣传干事进行宣传

这是一个严格按照单一职责原则重构的代码,一个类只负责一项职责,很显然,它的逻辑比上述重构(负责多项职责)简单了很多

综上所述,单一职责原则的优点如下:
1.降低职责间耦合度
2.降低模块设计的复杂度
3.提高代码的可读性
4.提高系统的可维护性
5.降低职责扩散或需求变更引发的风险

蜗牛学院,只为成就更好的你!这样创新的模式,值得你的选择!

还在等什么,赶快关注蜗牛学院官方微信,加入到蜗牛学院的大家庭中来吧!

20181009_153045_341.jpg

版权所有,转载本站文章请注明出处:蜗牛学院在线课堂, http://www.mountsinaibaptistchurch.org/note/6
上一篇: 原理:单例模式的陷阱
下一篇: 实验:Calendar对象计算时间差
提示:登录后添加有效评论可享受积分哦!