您当前的位置: 首页 > 

Dongguo丶

暂无认证

  • 1浏览

    0关注

    472博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

单一职责原则

Dongguo丶 发布时间:2018-08-12 15:40:30 ,浏览量:1

定义:

对类来说的,即一个类应该只负责一项职责。

问题由来:

类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,,由于类T承担的职责有多个(p1,p2),职责P1的变化有可能会导致原本运行正常的职责P2功能发生故障。

以交通工具案例讲解,我们有交通工具摩托车、汽车、飞机供我们选择。

package com.dongguo.principle.singleresponsibility1;

/**
 * @author Dongguo
 * @date 2021/8/21 0021-18:17
 * @description:交通工具类
 */
class Vehicle {
    /**
     * @author Dongguo 
     * @description: 摩托车汽车在公路上运行,飞机在天上飞
     */
    public void run(String vehicle) {
        System.out.println(vehicle + " 在公路上运行....");
    }
}
package com.dongguo.principle.singleresponsibility1;

/**
 * @author Dongguo
 * @date 2021/8/21 0021-18:15
 * @description:单一职责原则
 */
public class SingleResponsibility {
    public static void main(String[] args) {

        Vehicle vehicle = new Vehicle();
        vehicle.run("摩托车");
        vehicle.run("汽车");
        vehicle.run("飞机");
    }
}
运行结果:
摩托车 在公路上运行....
汽车 在公路上运行....
飞机 在公路上运行....

在交通工具类Vehicle的run 方法中,违反了单一职责原则,不可能所有的交通工具都可以在公路上运行,摩托车汽车在公路上运行,而飞机应该在天上飞

解决方案:

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

根据交通工具运行方法不同,分解成不同类即可,即将交通工具类Vehicle分解成陆上交通工具RoadVehicle、天上交通工具AirVehicle

package com.dongguo.principle.singleresponsibility2;

/**
 * @author Dongguo
 * @date 2021/8/21 0021-19:27
 * @description: 陆上交通工具
 */
public class RoadVehicle {
    public void run(String vehicle) {
        System.out.println(vehicle + "公路运行");
    }
}
package com.dongguo.principle.singleresponsibility2;

/**
 * @author Dongguo
 * @date 2021/8/21 0021-19:27
 * @description: 天上交通工具
 */
public class AirVehicle {
    public void run(String vehicle) {
        System.out.println(vehicle + "天空运行");
    }
}
package com.dongguo.principle.singleresponsibility2;


/**
 * @author Dongguo
 * @date 2021/8/21 0021-19:27
 * @description:
 */
public class SingleResponsibility {
    public static void main(String[] args) {
        RoadVehicle roadVehicle = new RoadVehicle();
        roadVehicle.run("摩托车");
        roadVehicle.run("汽车");
        AirVehicle airVehicle = new AirVehicle();
        airVehicle.run("飞机");
    }
}
运行结果:
摩托车公路运行
汽车公路运行
飞机天空运行

我们发现这样修改花销是很大的,除了将原来的类分解之外,还需要修改客户端。

如果直接修改Vehicle 类,改动的代码会比较少

妥协示例(项目中常见的单一职责违背可接受示例)

说到单一职责原则,很多人都会不屑一顾。因为它太简单了。稍有经验的程序员即使从来没有读过设计模式、从来没有听说过单一职责原则,在设计软件时也会自觉的遵守这一重要原则,因为这是常识。在软件编程中,谁也不希望因为修改了一个功能导致其他的功能发生故障。而避免出现这一问题的方法便是遵循单一职责原则。虽然单一职责原则如此简单,并且被认为是常识,但是即便是经验丰富的程序员写出的程序,也会有违背这一原则的代码存在。为什么会出现这种现象呢?因为有职责扩散。

所谓职责扩散,就是因为某种原因,职责P被分化为粒度更细的职责P1和P2.

比如:类T只负责一个职责P,这样设计是符合单一职责原则的。后来由于某种原因,也许是需求变更了,也许是程序的设计者境界提高了,需要将职责P细分为粒度更细的职责P1,P2,这时如果要使程序遵循单一职责原则,需要将类T也分解为两个类T1和T2,分别负责P1、P2两个职责。但是在程序已经写好的情况下,这样做简直太费时间了。所以,简单的修改类T,用它来负责两个职责是一个比较不错的选择,虽然这样做有悖于单一职责原则。(这样做的风险在于职责扩散的不确定性,因为我们不会想到这个职责P,在未来可能会扩散为P1,P2,P3,P4……Pn。所以记住,在职责扩散到我们无法控制的程度之前,立刻对代码进行重构。)

package com.dongguo.principle.singleresponsibility3;

/**
 * @author Dongguo
 * @date 2021/8/21 0021-19:40
 * @description: 这里虽然没有在类这个级别上遵守单一职责原则,但是在方法级别上,仍然是遵守单一职责
 */
public class Vehicle {
    
    public void run(String vehicle) {
        System.out.println(vehicle + " 在公路上运行....");
    }

    public void runAir(String vehicle) {
        System.out.println(vehicle + " 在天空上运行....");
    }
}

package com.dongguo.principle.singleresponsibility3;

/**
 * @author Dongguo
 * @date 2021/8/21 0021-19:40
 * @description:
 */
public class SingleResponsibility {
    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();
        vehicle.run("摩托车");
        vehicle.run("汽车");
        vehicle.runAir("飞机");
    }
}
运行结果:
摩托车 在公路上运行....
汽车 在公路上运行....
飞机 在天空上运行....

可以看出,这种修改没有改动原来的方法,而是在类中添加了一个方法,这样虽然也违背了单一职责原则,但在方法级别上却是符合单一职责原则的,因为它并没有改动原来方法的代码。

遵循单一职责的好处:
  1. 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
  2. 提高类的可读性,提高系统的可维护性;
  3. 变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,对其他功能无影响,这对系统的扩展性,维护性都有非常大的帮助

通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则:只有类中方法足够少,可以在方法级别保持单一职责原则。

例如本文所举的这个例子,它太简单,它只有一个方法,所以,无论在代码还是在方法级别违背单一职责原则,都不会造成太大的影响。 实际应用中的类都要复杂的多,一旦发生职责扩散而需要修改类时,除非这个类本身非常简单,否则还是要遵循单一职责原则。

难点:
  • 职责划分无量化标准
  • 单一职责妥协:项目中是很难完美的体现单一职责的,由于项目的开发环境,工作量,开发人员的技术水平等因素,往往会违背单一职责的原则

单一职责只是提出了一个编写程序的标准,可以用是否遵循单一职责来衡量接口或类的设计是否优良话,但是单一职责原则最难划分的就是职责,职责没有一个量化的标准,一个类到底负责哪些职责,这些职责该如何细化,都要从实际的项目去考虑,所以应因项目而异,因环境而异。

单一职责与接口隔离的区别:
  1. 单一职责原则注重的是职责;而接口隔离原则注重对接口依赖的隔离。
  2. 单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节; 而接口隔离原则主要约束接口,主要针对抽象,针对程序整体框架的构建。

关注
打赏
1638062488
查看更多评论
立即登录/注册

微信扫码登录

0.1667s