设计原则之单一职责

2020-09-15 10:22:27 浏览数 (1)

1. 单一职责原则

基本介绍:一个类只负责一项职责,完成一个单一的功能。

错误的示范
代码语言:javascript复制
package principle.singleresponsibility.error;

/**
 * 单一职责错误示范
 * @author huangfu
 */
public class SingleResponsibilityError {
    public void mobile (String vehicle){
        System.out.println(vehicle   "在公路上跑!");
    }
}
代码语言:javascript复制
package principle.singleresponsibility.error;

/**
 * 单一职责错误的示范的测试
 * @author huangfu
 */
public class TestSingleResponsibilityError {

    public static void main(String[] args) {
        SingleResponsibilityError singleResponsibilityError = new SingleResponsibilityError();
        singleResponsibilityError.mobile("汽车");
        singleResponsibilityError.mobile("轮船");
        singleResponsibilityError.mobile("飞机");
    }
}
结果
代码语言:javascript复制
汽车在公路上跑!
轮船在公路上跑!
飞机在公路上跑!

上述就违反了单一职责原则,对于不同的交通工具,代码逻辑完全耦合在一起,我们无论修改那一类的交通工具,都会影响其他两种数据

正确的示范

定义接口

代码语言:javascript复制
package principle.singleresponsibility.correct;

/**
 * @author huangfu
 */
public interface TrafficTool {
    /**
     * 交通工具
     * @param trafficToolName
     */
    void mobile(String trafficToolName);
}

定义基类,这个主要是对一类的交通工具进行抽象定义,具体的实现可以由子类实现也可直接使用父类的方法

代码语言:javascript复制
package principle.singleresponsibility.correct.base;

import principle.singleresponsibility.correct.TrafficTool;

/**
 * 陆地交通工具
 * @author huangfu
 */
public abstract class LandTrafficTool implements TrafficTool {
    @Override
    public void mobile(String trafficToolName) {
        System.out.println(trafficToolName   "在陆地跑!");
    }
}
代码语言:javascript复制
package principle.singleresponsibility.correct.base;

import principle.singleresponsibility.correct.TrafficTool;

/**
 * 海上交通工具
 * @author huangfu
 */
public abstract class MaritimeTrafficTool implements TrafficTool {

    @Override
    public void mobile(String trafficToolName) {
        System.out.println(trafficToolName   "在海上跑!");
    }
}
代码语言:javascript复制
package principle.singleresponsibility.correct.base;

import principle.singleresponsibility.correct.TrafficTool;

/**
 * 天空交通工具
 * @author huangfu
 */
public abstract class SkyTrafficTool implements TrafficTool {
    @Override
    public void mobile(String trafficToolName) {
        System.out.println(trafficToolName   "在天空上飞");
    }
}

定义具体的实现,可以使用抽象方法也可自己实现逻辑

代码语言:javascript复制
package principle.singleresponsibility.correct;

import principle.singleresponsibility.correct.base.SkyTrafficTool;

/**
 * 飞机交通工具
 * @author huangfu
 */
public class AircraftTrafficTool extends SkyTrafficTool {

    @Override
    public void mobile(String trafficToolName) {
        super.mobile(trafficToolName);
    }
}
代码语言:javascript复制
package principle.singleresponsibility.correct;

import principle.singleresponsibility.correct.base.LandTrafficTool;

/**
 * 汽车交通工具
 * @author huangfu
 */
public class CarTrafficTool extends LandTrafficTool {
    @Override
    public void mobile(String trafficToolName) {
        super.mobile(trafficToolName);
    }
}
代码语言:javascript复制
package principle.singleresponsibility.correct;

import principle.singleresponsibility.correct.base.MaritimeTrafficTool;

/**
 * 轮船类交通工具
 * @author huangfu
 */
public class SteamshipTrafficTool extends MaritimeTrafficTool {
    @Override
    public void mobile(String trafficToolName) {
        super.mobile(trafficToolName);
    }
}
代码语言:javascript复制
package principle.singleresponsibility.correct;

import principle.singleresponsibility.correct.base.LandTrafficTool;

/**
 * 特殊的交通工具:马
 * @author huangfu
 */
public class HorseLandTrafficTool extends LandTrafficTool {
    @Override
    public void mobile(String trafficToolName) {
        System.out.println(trafficToolName   "在大草原上跑!");
    }
}

测试类

代码语言:javascript复制
package principle.singleresponsibility.correct;

/**
 * @author huangfu
 */
public class TestTrafficTool {

    public static void main(String[] args) {
        //汽车类
        CarTrafficTool carTrafficTool = new CarTrafficTool();
        //飞机类
        AircraftTrafficTool aircraftTrafficTool = new AircraftTrafficTool();
        //轮船类
        SteamshipTrafficTool steamshipTrafficTool = new SteamshipTrafficTool();
        //特殊的交通工具 马
        HorseLandTrafficTool horseLandTrafficTool = new HorseLandTrafficTool();

        carTrafficTool.mobile("兰博基尼");
        aircraftTrafficTool.mobile("南航");
        steamshipTrafficTool.mobile("泰坦尼克号");
        horseLandTrafficTool.mobile("汗血宝马");
    }
}
结果
代码语言:javascript复制
兰博基尼在陆地跑!
南航在天空上飞
泰坦尼克号在海上跑!
汗血宝马在大草原上跑!

上述的完全的描述了单一职责的原则,对某一类交通工具的修改,并不会影响到全局的功能,也可以基于自己的需求来定制自己的交通工具,而不会对全局的功能产生影响!

如何理解单一职责原则呢?

对于单一职责原则我的理解是:一个类只负责完成一个职责或者功能。不要涉及大而全的类,要设计粒度小、功能单一的类。单一职责原则是为了实现代码高内聚、低耦合,提高代码的复用性、可读性、可维护性。

是否有必要对类做一个精准的划分呢?

其实对于不同的业务场景对于单一职责原则的理解都是不一样的,我举个例子是我在极客时间上王争大佬的《设计模式之美》举的一个例子,我觉得甚好,充分的说明了,在不同的业务场景下,类的职责划分也不尽相同!

我们模拟一个在社交产品中描述用户信息的类

代码语言:javascript复制
package principle.singleresponsibility.entity;

/**
 * 用户信息
 * @author huangfu
 */
public class UserInfo {
    private String userId;
    private String userName;
    private String sex;
    private Integer age;
    private String email;
    private String phone;
    private long createTime;
    private long lastLoginTime;
    /**
     * 省
     */
    private String provinceOfAddress;
    /**
     * 市
     */
    private String cityOfAddress;
    /**
     * 区
     */
    private String regionOfAddress;
    /**
     * 详细地址
     */
    private String detailedAddress;
}

主要争论有两点,第一是觉得这个类符合单一职责,因为包含的都是跟用户相关的信息,所有的属性和方法都隶属于用户这样一个业务模型,满足单一职责原则!

持不相同的观点:因为这个类里面地址所占比重比较高,所以应该将地址单独抽出来,形成一个userAddress类!这样两个类的职责就更加单一了!

其实两种说法都对,但是他们没有区分业务场景,刚刚也说了,不同的业务模型所对应的设计方案也不尽相同

如果说在社交产品中,地址信息和其他信息完全一致都是做展示用,第一种说法就对,没有必要拆分,他们确实属于一个业务模型,但是如果后来产品做大,用户的地址信息可能会用作用户的收件地址,那么第二种方式就对,因为用户信息和物流信息并不属于一个业务模型!

那么我们还可以在思考,公司越做越好,肯定不止一个社交产品。公司领导希望所有的社交产品的账号和用户信息互通,那么此时我们需要将 userName,sex,phone等信息也拆分出来,以供其他系统使用!

那么我们如何判断我们的类是否足够单一呢?

不同的应用场景、不同阶段的需求背景、不同的业务层面,对同一个类的职责是否单一,可能会有不同的判定结果。实际上,一些侧面的判断指标更具有指导意义和可执行性,比如,出现下面这些情况就有可能说明这类的设计不满足单一职责原则:

  • 类中的代码行数、函数或者属性过多;
  • 类依赖的其他类过多,或者依赖类的其他类过多;
  • 私有方法过多;
  • 比较难给类起一个合适的名字;
  • 类中大量的方法都是集中操作类中的某几个属性。
总结

事实上,单一职责设计原则正式代码 高内聚低耦合 设计的基石,他通过拆分不同业务,避免不相关的业务耦合在一起,从而提高了代码的高内聚;同时因为类的职责单一,他的耦合性也会相应降低,从而完成开发中一直提倡的 高内聚,低耦合

0 人点赞