前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计原则之单一职责

设计原则之单一职责

作者头像
止术
发布2020-09-15 10:22:27
2090
发布2020-09-15 10:22:27
举报
文章被收录于专栏:求道求道

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等信息也拆分出来,以供其他系统使用!

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

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

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JAVA程序狗 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 单一职责原则
    • 错误的示范
      • 结果
        • 正确的示范
          • 结果
            • 总结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档