单一职责原则

1. 单一职责原则的定义

单一职责原则(Single Responsibility Principle,SRP)

又称单一功能原则,由罗伯特·C.马丁(Robert C. Martin)于《敏捷软件开发:原则、模式和实践》一书中提出的。这里的职责是指类变化的原因,单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分(There should never be more than one reason for a class to change)。

该原则提出对象不应该承担太多职责,如果一个对象承担了太多的职责,至少存在以下两个缺点:

  1. 一个职责的变化可能会削弱或者抑制这个类实现其他职责的能力;
  2. 当客户端需要该对象的某一个职责时,不得不将其他不需要的职责全都包含进来,从而造成冗余代码或代码的浪费。

2. 单一职责原则的优点

单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。如果遵循单一职责原则将有以下优点。

  • 降低类的复杂度。一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。
  • 提高类的可读性。复杂性降低,自然其可读性会提高。
  • 提高系统的可维护性。可读性提高,那自然更容易维护了。
  • 变更引起的风险降低。变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响。

3. 单一职责原则的实现方法

单一职责原则是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,再封装到不同的类或模块中。而发现类的多重职责需要设计人员具有较强的分析设计能力和相关重构经验。下面以交通工具运行方式为例介绍单一职责原则的应用。

【例】众所周知,交通工具有汽车这种陆地上的,也有飞机这种天上的,也有轮船,如果控制交通工具的类把所有交通工具的运行都放到一个方法去执行那么会出现这种情况:

/**
 * @Author lizeyu
 * @Date 2020/4/7 9:38
 */
public class single_test {
    public static void main(String[] args) {
        Vehicle car = new Vehicle("汽车");
        car.run(car.getname());
        Vehicle airPlane = new Vehicle("飞机");
        airPlane.run(airPlane.getname());
        Vehicle ship = new Vehicle("轮船");
        ship.run(ship.getname());
    }
}

class Vehicle{
    private String name;

    public Vehicle(String name) {
        this.name = name;
    }

    public String getname() {
        return name;
    }

    public void setname(String name) {
        this.name = name;
    }

    public void run(String name) {
        System.out.println(name+"交通工具是在陆地上运行");
    }
}

运行结果

汽车交通工具是在陆地上运行
飞机交通工具是在陆地上运行
轮船交通工具是在陆地上运行

由上面我们可以知道一个交通工具的总类去负责每种类型的交通工具的运行方式,它负责的太宽了,导致运行出现逻辑问题。我们大家都明白目前交通方式分为三类海陆空,我们讲交通工具类分为陆地交通水上交通天空交通,每一个类负责各自的运行方式。

第一次优化

/**
 * @Author lizeyu
 * @Date 2020/4/7 9:38
 */
public class single_test {
    public static void main(String[] args) {
        LandVehicle car = new LandVehicle("汽车");
        car.run(car.getName());

        AirVehicle airPlane = new AirVehicle("飞机");
        airPlane.run(airPlane.getName());

        WaterVehicle ship = new WaterVehicle("轮船");
        ship.run(ship.getName());
    }
}

class LandVehicle{
    private String name;

    public LandVehicle(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void run(String name) {
        System.out.println(name+"交通工具是在陆地上运行");
    }
}

class AirVehicle{
    private String name;

    public AirVehicle(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void run(String name) {
        System.out.println(name+"交通工具是在天上运行");
    }
}

class WaterVehicle{
    private String name;

    public WaterVehicle(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void run(String name) {
        System.out.println(name+"交通工具是在水上运行");
    }
}

运行结果

汽车交通工具是在陆地上运行
飞机交通工具是在天上运行
轮船交通工具是在水上运行

这样看起来就正常了,但是又有一个问题值得我们思考,一个很简单的问题居然需要创建三个类,内存消耗太大。我们有没有方法不需要这么浪费内存又做到单一职责呢?

第二次优化

/**
 * @Author lizeyu
 * @Date 2020/4/7 9:38
 */
public class single_test {
    public static void main(String[] args) {
        Vehicle transition = new Vehicle();

        transition.landRun("汽车");
        transition.airRun("飞机");
        transition.waterRun("轮船");
    }
}

class Vehicle{

    public void airRun(String name) {
        System.out.println(name+"交通工具是在天上运行");
    }

    public void waterRun(String name) {
        System.out.println(name+"交通工具是在水上运行");
    }

    public void landRun(String name) {
        System.out.println(name+"交通工具是在陆地上运行");
    }
}

运行结果

汽车交通工具是在陆地上运行
飞机交通工具是在天上运行
轮船交通工具是在水上运行

整体看我们并没有严格按照单一职责原则,这是什么意思呢?我们看到我们在客户端里,我们构造了海陆空三个类,为什么要这么做呢?因为我们交通工具类负责了三个职责。显然在类级别上违反了单一职责原则,但是我们这样做代码简单了很多,满足了程序设计的易读性。扩展简单,如果这时候又将汽车分为更细的类,那马我们只需要更改客户端的代码,而封装好的方法不需要改动,显然符合可扩展性。其它各种性质都可以满足。

这么看来我们可以得出结论,第二次优化以后虽然在类级别违反了单一职责原则,但是在方法上遵循了该原则,而且这样使得程序变得更加简单、更加适合使用。

4. 总结

单一职责原则注意事项和细节

  • 降低类的复杂度,一个类只负责一项职责
  • 提高类的可读性,可维护性
  • 降低变更引起的风险
  • 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码(类)级别违反单一职责原则;只有类中方法数量足够少,才可以在方法级别违反单一职责原则。

你可能感兴趣的:(设计模式,java)