精华内容
下载资源
问答
  • 单一职责原则
    2022-04-11 16:29:51

    单一职责原则定义

    一个类、接口、方法只负责一项职责,不要存在多于一个导致类变更的原因

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

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

    使用好单一职责原则,可以降低类的复杂度,提高类的可读性,提高系统的可维护性,降低因变更参数引起的风险等。但使用单一职责原则也不是任何情况下都追求完全的遵守。该原则适用于类也适用于方法。

    我们以一个方法级别的例子来理解

    例子为假设我们对一门新课的直播课和录播课进行不同的加密或其他操作,如果仅输出是否是直播课或录播课,一个类中判断没问题,如果进行加密或权限其他操作,则要遵循单一职责原则,拆分到不同的类中分别处理,会使代码更简洁更易读。

    public class Course {
        public void study(String courseName){
            if ("直播课".equals(courseName)){
                System.out.println(courseName + "不能快进");
            }else {
                System.out.println(courseName + "可以反复观看");
            }
        }
    }
    public class CourseTest {
        public static void main(String[] args) {
            Course course = new Course();
            course.study("直播课");
            course.study("录播课");
        }
    }
    

    如果我们要对以上不同课程进行加密和加权限,则这么写后面维护起来会有问题。我们采用以下方法:将上面课程类拆分为直播课类和录播课类再分别实现

    //直播课类,单一类处理单一逻辑,进行加密逻辑或其他
    public class LiveCourse {
        public void study(String courseName){
            System.out.println(courseName + "不能快进");
        }
    }
    //录播课类,单一类处理单一逻辑,进行加密逻辑或其他
    public class ReplyCourse {
        public void study(String courseName){
            System.out.println(courseName + "可以反复观看");
        }
    }
    

    其实很简单,就是每一个功能或一个小模块单独进行处理,维护起来也很容易维护

    我们再举一个方法级别的例子
     public void modifyUserInfo(String userName,String Password,Boolean bool){
            if (){//符合某些逻辑置为true
                bool = true;
            }
            if (bool){
                //修改username相关
            }else {
                //修改password相关
            }
        }
        //以上方法拆分为以下方法,如果拆的不能再拆了,说明符合单一职责原则
        
        public void modifyUserName(String userName){
            //修改username相关
        }
        public void modifyUserName(String Password){
            //修改password相关
        }
    

    对单一职责原则的使用也不用完全的遵照,有时候不拆分会比拆分更易读,是否使用及使用的程度需要你自己去把握,去斟酌。上面的例子不太恰当,但是大概意思的对的,理解就行了。

    更多相关内容
  • NULL 博文链接:https://lijie-insist.iteye.com/blog/2190970
  • 单一职责原则

    千次阅读 2021-03-12 15:31:36
    1. 单一职责原则的定义 单一职责原则(Single Responsibility Principle,SRP) 又称单一功能原则,由罗伯特·C.马丁(Robert C. Martin)于《敏捷软件开发:原则、模式和实践》一书中提出的。这里的职责是指类变化...

    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. 总结

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

    • 降低类的复杂度,一个类只负责一项职责
    • 提高类的可读性,可维护性
    • 降低变更引起的风险
    • 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码(类)级别违反单一职责原则;只有类中方法数量足够少,才可以在方法级别违反单一职责原则。
    展开全文
  • 主要介绍了PHP面向对象五大原则之单一职责原则(SRP),结合实例形式详细分析了单一职责原则(SRP)的概念、原理、定于与使用方法,需要的朋友可以参考下
  • 单一职责原则(SRP)

    2022-04-29 21:32:54
    什么是单一职责原则 单一职责原则(英文名为Single Responsibility Principle,简称SRP)是Robert C. Martin提出的SOLID软件设计原则中的第一个字母S。 Robert C. Martin给出的定义为, 有且仅有一个原因导致类的...

    什么是单一职责原则

    单一职责原则(英文名为Single Responsibility Principle,简称SRP)是Robert C. Martin提出的SOLID软件设计原则中的第一个字母S

    Robert C. Martin给出的定义为, 有且仅有一个原因导致的变化。

    A class should have one, and only one, reason to change.

    而本人更偏向于Wiki上对SRP的描述, 其单一职责原则应该运用于模块, 以及文件

    The single-responsibility principle (SRP) is a computer-programming principle that states that every module, class or function in a computer program should have responsibility over a single part of that program’s functionality, and it should encapsulate that part.

    首先说一说职责, 如果说直接从软件说起来,还是比较抽象的。那我打算从生活中的其他可见的方面来说一说。

    比如写一本小说,可能会分成3部,每一部讲述一段完整的故事,而每一部完整的故事,又有一系列单独的场景片段拼接起来,推动着故事的发展, 各个场景之间相互独立,又关联在一起。

    再比如说一个公司,可能由人力资源部后勤部门财务部门研发部门技术支持部门以及销售部门组成。每个部门都可以认为有着自己的单一职责,而每个部门之间都不是互相孤立有着联系,比如技术支持部门解决不了的问题会寻求研发部门的协助,研发部门会和人力资源部门合作进行技术人员招聘,人力资源部门会和财务部门进行工资结算,后勤部门会保证各个部门的后勤工作得到妥善的安排。从公司层面看,研发部门有自己的单一职责负责产品的研发相关的任务。而从研发部门内部来看,我们又可以将其划分为管理组测试组开发组运维组。然后开发组可能有分为前端组后端组基础架构组等,每一个小组也都有着自己的单一职责。我们从不同的角度看,似乎可以进行不同维度的单一职责的划分。那么比如主要专注于后端开发这个单一职责后端开发组,有两个人互换了不同的模块开发,其实对于其他的组来说基本是没有太多的影响和变化的。我们的软件开发也是如此,当你进行一个产品/项目开发的时候,是不是也是类似于从上而下的进行职责划分,从模块,到代码文件,到类,到每一个函数的的实现,每一个层级都有着自己的单一职责原则;并且这个原则可以让我们的程序在修改时带来更少的副作用,也便于更好做程序扩展。
    在这里插入图片描述
    本文以一个采用C++开发的样例项目为例:假设有这样一个项目,客户端需要开发一个PC端的Windows UI程序, 该程序可以从一个服务器定期获取数据,并且存储在本地后,UI程序可以对存储的数据进行展示。

    那么我们将从项目架构,模块,源文件,namespace, 类,以及函数几个方面来阐述单一职责原则,并且在文末进行总结。

    单一职责原则之项目架构

    当分析这个需求后,我们可以画出这样一个图, 首先从项目需求方面出发,将其功能进行职能划分, 如下图:

    1. 数据处理功能部分,从某个服务定时拉取最新的数据,进行处理后,存储到数据库
    2. UI数据展示,将从数据库读取数据进行展示,可以进行条件搜索

    在这里插入图片描述
    如果这个需求比较简单,我们假设先不考虑工期,那么可能有两种方案:

    1. 方案1: UI数据展示功能和数据处理功能都放在一个进程内部
    2. 方案2: UI数据展示功能和数据处理功能分别实现为两个进程

    先说方案1, 两个模块之间不需要直接的交互,通过数据库进行了间接的交互。这种设计可能带来两个问题:

    1. 两个模块可能会出现互相影响。比如UI数据展示相关的模块出现Crash,也会导致数据处理模块停止工作,反之亦然。 更比如编写C++,可能出现堆内存溢出问题,如果数据处理部分部分处理时产生内存溢出,踩到了UI数据展示功能部分的对象所在内存,那么可能追查原因也变的更加复杂。
    2. 两个功能模块都在同一个进程中,在使用过程中必须共进退。那么部署使用也会存在问题,比如当你做了UI数据展示
      功能的一些修复后,在做更新的时候,数据处理功能部分,一般也需要停止工作。或者说当你关闭UI退出的时候,数据处理也随之停止了。

    从职能上说这两个功能完全可以通过不同的进程隔离开来,做成两个进程,我们可以做到有如下优势:

    1. 两个功能可以完全由不同的人去开发,甚至是不同的技术栈的人。比如数据处理功能部分,需要和服务器交互,数据处理,以及和DB的一些操作,那么这个人员可以选择Java, Golang等等,可以提高其开发效率。
    2. 两个进程互不干扰,你甚至可以分布在不同的机器上,不同的操作系统。而且数据处理可以单独做成一个服务,不用随着UI数据展示窗口关闭而停止数据更新了。
    3. 后续的程序更新维护也互不影响,并且问题追踪,也将更容易定位。

    根据其需求功能的角度出发,对其职责进行划分,我们将其从架构层面可以分为两个部分: 数据处理部分采用Windows服务进程,而UI数据展示部分采用程序员所熟悉的图形库进行开发, 其结构如下:
    在这里插入图片描述

    当然以上内容都是可以讨论的,如果领导和你说,1个人开发,5天代码完成,1天测试,那么请不要纠结单一职责原则

    单一职责原则之模块划分

    在上学时候,当我我第一次见到真实运转的项目代码的时候,才知道原来一个程序真的需要划分为多个Libary来进行调用。也就是说会将一些独立功能的模块单独的组织在一起,编译生成DLL/SO文件,让其他模块可以进行调用。

    我以Visual Studio的工程为例, Visual Studio的组织结构最上层的叫做解决方案,也就是保存为sln的文件,然后可以在解决方案中增加项目, 而每一个项目可以编译/链接生成为一个可执行程序(exe),动态链接库(dll),静态库(lib) 等。

    如果我们要做这个数据处理的程序,需要至少具备以下几个模块:

    1. Log 模块用于调试
    2. 获取数据,假设这里是HTTP接口获取程序
    3. 数据存储: 在预处理后的数据,进行数据存储,和数据库打交道的部分
    4. 数据操作: 组合了比如数据获取,数据预处理,以及数据存储
    5. 配置文件管理: 一般程序均有一个配置文件,可以控制一些参数(比如可能数据处理过程中需要一些参数)
    6. windows服务可执行程序

    如果我们将上面6个功能全部存放在一个项目中,那就是违背了单一职责原则。比如你想对数据存储部分做一些小的改动,但数据存储所提供的接口并不改动的情况下,那会导致整个项目都需要进行编译,生成新的可执行程序。而如果将数据存储剥离成独立的项目,以动态链接库的方式提供其方法,将会有以下几个好处:

    1. 数据存储提供的接口不发生变化的情况下,只需要编译改动的项目,并且替换的时候,只需要替换当前改动的动态链接库或者可执行文件
    2. 当如果未来需要扩展,有个新的应用程序(比如测试程序),也需要数据存储相关的功能后,就不必编写相同的代码,直接依赖于这个数据存储项目,并通过调用动态链接库的方式使用其提供的方法。
    3. 维护人员也可以更容易的对代码进行维护,结构清晰,不是所有的东西都柔和在一个工程中。

    其模块关系大致如下图:
    在这里插入图片描述
    当然了以上也并不是说一定是最符合单一职责原则的场景,我们重在理解遵循单一职责原则去划分不同的模块。否则讨论就容易变成谁是世界上最好的语言问题一样,哈哈。

    同理我们对于模块的划分,我们也可以将其保存在不同的目录文件中,除此之外,Visual Studio也提供了,即使是同一个工程下的文件,也可以用Filter对源文件进行逻辑划分,如下图是PocoNet库的工程:
    在这里插入图片描述
    那么对于UI数据展示模块也就不必赘述了。

    单一职责原则之源文件

    上一章节也有提到,C++中的源文件可以通过项目进行管理,也可以设置Filter,同样可以根据不同的功能将其放置在不同的目录。

    组织.cpp.h文件一般需要:

    1. 将紧密相关的类/函数放置在同一个文件中,大多数情况下你可能注意到很多第三方库的实现是一个.h中声明了一个class。这个不是绝对的,也可以一个头文件中存放多个class,我们其实主要理解,不要将大多数相对复杂的类,都防止在同一个文件中进行声明或者实现,可以将其拆分为多个文件保存。
    2. 还有时候经常碰到的问题是,当你在做类的实现的时候,会需要一些比较通用的实现:比如一些字符串常见的trim,大小写转换之类的,有时候就顺手写在了这个.cpp文件中。但如果其他cpp文件或者项目模块中也需要这一类的辅助操作呢,就容易造成重复的实现。应该做的是将这些通用实现都放到专门处理string的模块中。
    3. 头文件中一般会声明一些类或者函数等,也会存在宏定义或者枚举之类的。有时候会出现的问题是,比如一个头文件包含了类的声明,类依赖于一些其他的类型,所以也在include中包含了这些依赖;如果头文件中还含有一些枚举类型,而此时你需要在另一个模块中引用这个头文件,并且只需要用到里面的枚举类型,对于其他的类声明并不关心,但会因为头文件中类对其他的头文件的依赖,需要对当前的模块也进行一些依赖配置,但这些是多余的。那么就可以将这些枚举类型,剥离出一个新的头文件进行存储。

    说到这里就不得不吐槽一下,C++经常要写.h头文件中声明,然后.cpp做实现,比起C#这种只要写.cs文件来说麻烦许多。

    单一职责之namespace, 类和方法

    之所以把这三个放到一起说,是因为都已经属于代码层面。
    先说说namespace, 本意是防止命名空间污染问题,而从另一个角度看,namespace也可以看做是模块划分的一种方式。比如C++标注库, boost, Poco等都使用了namespace,并且有不同的命名空间比如std::chrono用于时间处理相关的, Poco::Net用于网络处理相关的。

    然后再来说说类,也是大多数文章提到类的单一职责原则。这些当然也扩展到其他语言的接口,或者C++的纯虚函数。我们来继续按照这个项目来看看其中一个糟糕的样例: 比如数据处理功能部分,设计了一个类DataProcess被服务调用实现了三个方法:

    • QueryData: 用于从服务器定期获取数据
    • HandleData: 对获取的数据进行一些验证,和一些预处理
    • StoreData: 将数据存储到数据库
      在这里插入图片描述

    这样设计是违背单一职责原则的,因为可能会发生以下情况:

    1. 如果说QueryData中从服务器端请求的格式发生了变化,其实这个并不应该影响到HandleDataStoreData, 因此他是可以剥离开来,专注于数据获取的操作
    2. 如果说StoreData数据存储的位置发生了变化,比如从SQLServer切换到Mysql, 也不应该影响到QueryDataHandleData部分,其也可以剥离开来,专注于数据存储相关的操作。

    那我们按照单一职责原则对其重新进行划分设计如下: 虽然图中的类只有一个方法,实际上在实现的时候会有很多的私有方法。而ServiceWorker像搭积木一样把这些类的功能组装起来,完成任务!
    在这里插入图片描述

    关于函数的单一职责划分也和类类似,我这里举一个不一样的,并且容易犯错误的例子。还是拿数据处理作为样例,假设获取的数据类似于如下:

    {
    "field1": "key1=value1;key2=value2;key3=value3",
    "field2": "abc"
    }
    

    如果在DataProcessor内部有个私有函数叫做 ParseData负责解析这个数据:
    在这里插入图片描述
    这个时候的函数样式类似于 (只是示例,并不是可编译的代码)如下,但是对于field1中我们目前只需要获取key3的值。

    DataObjectPtr DataProcessor::ParseData(const JsonData& data)
    {
        DataObjectPtr obj(new DataObject);
    	obj->m_filed_2 = data["field2"];
    	// 这里对data["field1"]进行字符串处理若干
    	// 通过字符串查找先找到`;key3`的位置然后进行处理
    	// 假设写了10来行
    	return obj;
    }
    

    这个示例会存在什么问题,就是将field1字段的处理流程放置在了ParseData中,那么可能对未来扩展存在如下问题:

    1. 如果没有特别的性能要求,未来很可能会对key1, key2的值同样需要解析出来,那么在这里更适合的方式是将所有的key=value都解析成map存放起来,便于访问。
    2. 单一职责原则应该将field1字段解析过程独立成一个函数;假设这个时候来了一个field3也是这种key=value的形式,则可以复用这个独立的函数去实现。

    例子简单,可能觉得不会有问题,但是当你的业务相对复杂,本身函数体已经比较大的情况下,很容易出现这样的错误编程方式,从而使得函数体越来越臃肿,也越来越难维护,重构的成本也越来越高。

    总结

    最后引用Robert C. Martin的一段话:

    What do I mean by “Principle”
    The SOLID principles are not rules. They are not laws. They are not perfect truths. The are statements on the order of “An apple a day keeps the doctor away.” This is a good principle, it is good advice, but it’s not a pure truth, nor is it a rule.

    这些原则并不是真理,而是一些从实践中得到的一些经验,让你远离未来可能碰到的麻烦。

    单一职责原则职责划分,每个人对于不同的业务和实现都有着自己的理解,而且项目也有着截止日期的约束,千万不要让原则束缚住我们,按照要求发布符合质量的产品是第一位的。

    世界上不是只有,我们很难用一个去界定所有的东西;但也要记住我们要懂得什么是,什么是

    本文也只是个人的一些总结,欢迎大家一起讨论,一起进步。

    参考

    这部分主要是列举了一些在文章编写时候,看过的书籍或者网站:
    [1]: 秦小波的<<设计模式之禅>>
    [2]: Robert C. Martin的<<架构整洁之道>> (孙宇聪 译)
    [3]: Wikipedia: Single-responsibility principle

    展开全文
  • 主要介绍了Java设计模式编程中的单一职责原则,这在团队开发编写接口时经常使用这样的约定,需要的朋友可以参考下
  • 一、单一职责原则简介、 二、单一职责原则代码示例 ( 反面示例 )、 1、不遵循单一职责原则的类、 2、测试类、 三、单一职责原则代码示例 ( 正面示例 | 类的单一职责 )、 1、用翅膀飞的鸟、 2、用脚走的鸟、 3、测试...





    一、单一职责原则简介



    单一职责原则 : 不要存在 多余一个 导致 类变更的原因 ;

    假设有一个类 , 负责 2 2 2 个职责 , 职责 1 1 1 和 职责 2 2 2 ;
    一旦 需求发生变更 , 如 职责 1 1 1 相关功能发生改变 ;
    修改该类的 职责 1 1 1 功能时 , 有可能导致原本运行正常的职责 2 2 2 发生故障 ;

    对于上述类 , 应该 分别针对 职责 1 1 1 和 职责 2 2 2 , 各自建立一个独立的类 , 这样就保证了系统的稳定性 ;
    这样修改 职责 1 1 1 和 职责 2 2 2 中的任何一个功能 , 都不会影响另外一个职责的功能 ;


    推荐的开发方法 : 使一个 类 / 接口 / 方法 只负责一项职责 ;


    单一职责优点 : 提高 类的 可读性 , 提高 系统的 可维护性 , 降低 类的复杂度 , 降低 变更引起的风险 ;

    类越简单 , 可读性越好 , 同时提高了可维护性 ;
    一个类只负责一个职责 , 比负责多个职责 , 类要 简单得多 ;
    变更是必然的 , 必须要接收变更 , 如果 单一职责原则遵守的好 , 当修改一个功能时 , 可以 显著降低对其它功能的影响 ;


    单一职责原则 不只是 面向对象 设计中特有的职责 , 只要是模块化的系统 , 都适合使用单一职责原则 ;





    二、单一职责原则代码示例 ( 反面示例 )




    1、不遵循单一职责原则的类


    Bird 类 , 代表了所有的鸟类 , 主要的移动方式是 用翅膀飞 , 和 用脚走 ;

    如果要加入新的鸟 企鹅 , 就需要修改该类的代码 , 在 if … else … 上添加新的分支 , 一旦修改 , 就会导致当前类存在潜在风险 , 影响其它的功能 ;

    package singleresponsibility;
    
    public class Bird {
        public void mainMoveMode(String name) {
            if ("鸵鸟".equals(name)) {
                System.out.println(name + " 用翅膀飞");
            } else {
                System.out.println(name + " 用脚走");
            }
        }
    }
    

    2、测试类


    package singleresponsibility;
    
    public class Main {
        public static void main(String[] args) {
            Bird bird = new Bird();
            bird.mainMoveMode("大雁");
            bird.mainMoveMode("鸵鸟");
        }
    }
    

    执行结果 :

    大雁 用脚走
    鸵鸟 用翅膀飞
    




    三、单一职责原则代码示例 ( 正面示例 | 类的单一职责 )



    上面反面示例中 , Bird 类承担了 2 2 2 个职责 , 用翅膀飞的鸟 和 用脚走的鸟 的职责都在一个类中实现 , 这就导致了一旦修改一个职责 , 另外一个也有可能被影响 ;


    1、用翅膀飞的鸟


    package singleresponsibility;
    
    /**
     * 用翅膀飞的鸟
     *      本类的职责单一 , 只负责用翅膀飞的鸟的移动
     */
    public class FlyBird {
        public void mainMoveMode(String name) {
            System.out.println(name + " 用翅膀飞");
        }
    }
    

    2、用脚走的鸟


    package singleresponsibility;
    
    /**
     * 用脚走路的鸟
     *      本类的职责单一 , 只负责用脚走的鸟的移动
     */
    public class WalkBird {
        public void mainMoveMode(String name) {
            System.out.println(name + " 用脚走");
        }
    }
    

    3、测试类


    package singleresponsibility;
    
    public class Main {
        public static void main(String[] args) {
    
            FlyBird flyBird = new FlyBird();
            flyBird.mainMoveMode("大雁");
    
            WalkBird walkBird = new WalkBird();
            walkBird.mainMoveMode("鸵鸟");
        }
    }
    

    执行结果 :

    大雁 用脚走
    鸵鸟 用翅膀飞
    




    四、单一职责原则代码示例 ( 接口的单一职责 )




    1、反面示例


    该 IGood 接口负责两大块职责 , 获取商品信息 获取 名称 / 价格 , 管理商品 购买 / 退款 ;

    这个接口设计 , 违背了单一职责原则 ;

    package singleresponsibility;
    
    /**
     * 该接口负责两大块职责
     *      获取商品信息 获取 名称 / 价格
     *      管理商品 购买 / 退款
     * 这样就违背了单一职责原则
     */
    public interface IGood {
        /**
         * 获取商品名称
         * @return
         */
        String getName();
    
        /**
         * 获取价格
         * @return
         */
        double getPrice();
    
        /**
         * 购买商品
         */
        void buyGood();
    
        /**
         * 退款
         */
        void refund();
    }
    

    2、拆分出的接口 1


    package singleresponsibility;
    
    /**
     * 信息管理
     *      该接口负责 获取商品信息 获取 名称 / 价格
     */
    public interface IGoodInfo {
        /**
         * 获取商品名称
         * @return
         */
        String getName();
    
        /**
         * 获取价格
         * @return
         */
        double getPrice();
    }
    

    3、拆分出的接口 2


    package singleresponsibility;
    
    /**
     * 商品管理
     *      负责商品的 购买 / 退款
     */
    public interface IGoodManager {
        /**
         * 购买商品
         */
        void buyGood();
    
        /**
         * 退款
         */
        void refund();
    }
    

    4、接口实现类


    package singleresponsibility;
    
    /**
     * 商品实现类
     *      同时实现 IGoodManager 和 IGoodInfo 两个接口
     */
    public class GoodImpl implements IGoodManager, IGoodInfo{
        @Override
        public String getName() {
            return null;
        }
    
        @Override
        public double getPrice() {
            return 0;
        }
    
        @Override
        public void buyGood() {
    
        }
    
        @Override
        public void refund() {
    
        }
    }
    




    五、单一职责原则代码示例 ( 方法的单一职责 )



    如果一个方法中 , 存在了 大块的 if … else … 判定 , 说明应该将其拆分成两个不同的方法 ;


    1、反面示例


    package singleresponsibility;
    
    public class Good {
        /**
         * 更新商品的 名称 和 价格信息
         *      该方法的职责就不是单一职责的
         *      如果要针对 价格 信息修改策略进行修改
         *      会连带这 另外一个 职责 修改名称 , 也存了未知风险
         * @param name
         * @param price
         */
        public void updateGoodInfo(String name, double price) {
        }
    }
    

    2、单一职责示例


    package singleresponsibility;
    
    public class Good {
        /**
         * 更新商品的名称
         * @param name
         */
        public void updateGoodName(String name) {
        }
    
        /**
         * 更新商品的价格
         * @param price
         */
        public void updateGoodPrice(double price) {
        }
    }
    
    展开全文
  • 1.什么是单一职责原则? 首先我们可以对某个类来说,即一个类应该只负责一项职责。如类A负责两个不同职责: 职责1,职责2。当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为A1,A2。 ...
  • 一、单一职责原则定义 单一职责原则是面向对象五个基本原则(SOLID)之一,也是最简单的面向对象设计原则,用于控制类的颗粒大小。单一职责定义如下: 单一职责原则(SRP:Single responsibility principle):一个...
  • 软件设计原则之单一职责原则

    多人点赞 热门讨论 2022-02-21 22:45:22
    单一职责原则(SRP:Single responsibility principle)又称单一功能原则,你可能觉得这个原则很简单,听起来的确是这样,不就是一个类,只做一件事嘛?真的是这样吗? 这个原则的英文是: There should never be ...
  • 文章目录 软件架构设计原则 单一职责原则 接口隔离原则 其他设计原则 软件架构设计原则 本文通过实例来讲解 单一职责原则 接口隔离原则 单一职责原则 单一职责(Simple Responsibility Pinciple, SRP) 是指不要存在...
  • 相信很多人都听过单一职责原则(Single Responsibility Principle),那么什么是单一职责原则,怎么才算单一职责原则呢,单一职责原则又有什么好处呢。 记得当初刚开始进入项目组做需求的时候,完全不清楚什么设计...
  • 单一职责原则简介

    千次阅读 2020-08-03 17:51:55
    参考文章:面向对象编程的六大原则(1)--单一职责原则 1. 什么是单一职责  单一职责原则(Single responsibility principle,简称SRP),顾名思义,是指一个类或者一个模块应该有且只有一个职责,它是面向对象...
  • 单一职责原则可以使类的复杂度降低,实现什么职责都有清晰明确的定义;类的可读性提高,复杂度降低;可读性提高了,代码就更容易维护;变更(需求是肯定会变)引起的风险(包括测试的难度,以及需要测试的范围)降低...
  • 单一职责原则: 是将某一职责的方法全放在一个接口中,这时候就会出现实现该接口的类必须实现该接口中自己用不到的方法(违背接口隔离原则) 接口隔离原则: 是为了将胖接口分成粒度更细的接口,每个类仅仅实现自己所...
  • 简单通俗的来说:一个类只负责一项职责
  • 1.单一职责原则

    2021-05-31 15:16:49
    一、单一职责原则定义   单一职责原则定义:一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。   另外一种定义:就一个类而言,应该仅有一个引起它变化的原因。 二、单一职责原则分析   (1...
  • 主要为大家详细介绍了单一职责原则的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 1 简介 1.1 定义 不要存在多于一个导致类变更的原因。该原则备受争议,争议之处在于对职责的定义,...以上的设计依旧很差,总不能一味堆砌 ifelse 添加鸟类,结合该业务逻辑,考虑分别实现类职责,即根据单一原则创建两
  • SOLID:SOLID原则并非单纯的1个原则,而是由5个设计原则组成,它们分别是:单一职责原则、开闭原则、里式替换原则、接口隔离原则和依赖反转原则,SOLID由5个设计原则的头一个字母组成。 如何理解单一职责原则(SRP)...
  • 文章的开头我们提到了 SOLID 原则,实际上,SOLID 原则并非单纯的 1 个原则,而是由 5个设计原则组成的,它们分别是:单一职责原则、开闭原则、里式替换
  • 学习设计模式首先要明白所有原则都是为了达到面向对象设计的可扩展可复用可维护性而出现的。对于设计模式的原则,不同的书说法不一样,有的6个有的7个,单一职责原则和接口隔离原则多数只提了一个。
  • SOLID原则由5个原则组成,他们分别是:单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖反转原则。 2. 单一职责原则 单一职责原则的英文是 Single Responsibility Principle,缩写为 SRP。这个原则的...
  • 接口隔离原则和单一职责原则区别 单一职责原则是备受争议的原则,根据不同的业务逻辑,它会将系统功能模块划分成不同种类,产生多样的接口,同时每个接口尽量只包含一个功能(方法)。 而产生争议的原因就是这个业务...
  • 提高类的可读性,可维护性 降低变更引起的风险 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中方法数量足够少,可以在方法级别保持单一职责原则 部分引用:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 73,376
精华内容 29,350
关键字:

单一职责原则

友情链接: c++primerplus6-zwb.pdf.zip