• 设计模式——简单说(单一职责原则)


    单一职责原则的英文是Single Responsibility Principle,简称SRP。

    定义:应该有且仅有一个原因引起类的变更。

    如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会影响到其他的职责,另外,把多个职责耦合在一起,也会影响复用性。

    举个例子:

    /**
     * 水壶的接口
     */
    public interface Ikettle {
        public void lidButton();
       public void powerButton();
       public void powerConnector(); public void getWater(); }

    以上这个接口是不是一眼就看出了问题?

    我们只要这个水壶的接口。

     然而他却打开了盖子给自己装水了。好像不太需要。

    有人说也可以啊,那我们再加个烧水,再加个倒水。这个接口还能复用到我要生产的统一接口吗?明显有很多多余的。

    这个原则备受争议,因为在设计时,要怎么去划分类的职责,什么是类的职责?

    一个职责一个接口,但问题是“职责”没有一个量化的标准,一个类到底要负责那些职责?这些职责该怎么细化?细化后是否都要有一个接口或类?

    /**
     * 水壶的接口
     */
    public interface Ikettle {
        public void openLid();
        public void closeLid();
        public void powerOnButton();
        public void powerOffButton();
        public void powerOnConnecter();
        public void powerOffConnecter();
    }

    我准备生成一个水壶了:

    public class Midea1601 implements Ikettle{
    
        @Override
        public void openLid() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void closeLid() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void powerOnButton() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void powerOffButton() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void powerOnConnecter() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void powerOffConnecter() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void getWater() {
            // TODO Auto-generated method stub
            
        }
     
    }

    我们要使用了:

    public class UseKettle {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Midea1601 kettle= new Midea1601();
            
        }
    }

    然后你突然发现没有法用啊??!!

    没办法装水啊等等。。。

    看来要教教了。。。

    public interface IUseKettle {
        public void getWater(int waterLevel);
        public void boilWater();
        public void outWater(int waterLevel);
    }

    到了出厂了总是要拿来直接用的,改改吧。。

    public class Midea1601 implements Ikettle,IUseKettle{
    
     
        @Override
        public void getWater(int waterLevel) {
            // TODO Auto-generated method stub
            openLid();
            int level =0;
            for(int i=0;i<waterLevel;i++) {
                level++;
                try {
                    Thread.sleep(1000);
                }catch(Exception e) {
                    
                }    
            }
            closeLid();
        }
    
        @Override
        public void boilWater()  {
            // TODO Auto-generated method stub
            int temperature =0;
            for(int i=0;i<100;i++) {
                temperature++;
                try {
                    Thread.sleep(1000);
                }catch(Exception e) {
                    
                }    
            }
        }
    
        @Override
        public void outWater(int waterLevel) {
            // TODO Auto-generated method stub
            openLid();
            int level =0;
            for(int i=0;i<waterLevel;i++) {
                level++;
                try {
                    Thread.sleep(1000);
                }catch(Exception e) {
                    
                }    
            }
            closeLid();
        }
    
        @Override
        public void openLid() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void closeLid() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void powerOnButton() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void powerOffButton() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void powerOnConnecter() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void powerOffConnecter() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void getWater() {
            // TODO Auto-generated method stub
            
        }
     
    }
    public static void main(String[] args) {
            // TODO Auto-generated method stub
            Midea1601 kettle= new Midea1601();
            int waterLevel =100;
            kettle.getWater(waterLevel);
            kettle.boilWater();
         kettle.outWater(50);
    }

    好了可以烧水喝了。

    以上只是简单的说明,当然还有问题和要改进的地方。有空自己思考下。。。。。如何设计??

    这些都需要从实际的项目去考虑,从功能上来说,定义一个接口也没有错,实现了功能,而且设计简单,仅仅一个接口一个实现类,实际的项目我想大家都会这么设计。

    项目考虑可变因素和不可变因素,以及相关的收益成本比率,因此设计一个接口也可能是没有错的。

    过分细分类的职责也会人为地增加系统的复杂性。

    我是一个牛逼的类,我可以担任多职吗?

    答案当然是否定的。改起来就变成傻逼了。

    单一职责的好处:

    1、类的复杂度降低,实现什么职责都有清晰的明确的定意;

    2、可读性高

    3、可维护性高

    4、变更英气的风险降低

    单一职责适用于接口、类、同时也适用于方法。一个方法尽可能做一件事情。

    实践证明:

    这个原则非常优秀的,但是现实有现实的难处,你必须考虑项目工期、成本、策略。

    但类的设计尽量做到只有一个原因引起变化。

    对于接口,我们在设计的时候一定要做到单一,但是对于实现类就需要多方面考虑了。

  • 相关阅读:
    Iscroll滑动无效
    原生js 无缝滚动组件
    原生 js dialog弹窗组件
    html5 历史管理
    html5拖拽属性
    highcharts 数据图设置X轴间隔显示效果
    highcharts柱状图含有正负柱设置不同颜色的方法
    移动端滑动插件 swiper
    千分位添加和去掉方法
    dubbo常用类和路径
  • 原文地址:https://www.cnblogs.com/annkiny/p/10389586.html
Copyright © 2020-2023  润新知