zoukankan      html  css  js  c++  java
  • 六大设计原则(四)ISP接口隔离原则(上)

    ISP的定义

    • 首先明确接口定义
      • 实例接口
        • 我们在Java中,一个类用New关键字来创建一个实例。抛开Java语言我们其实也可以称为接口。假设Person zhangsan = new Person();我们称Person类就是张三的接口类。
      • 类接口
        • Java中用interface定义的接口。
    • 其次明确隔离定义
      • 客户端不应该依赖他不需要的接口。
      • 类间的依赖关系应当建立在最小的接口上。
        • 首先第一种说明客户端依赖接口,依赖的接口不能过于臃肿,所以要进行细化。第二种定义也是要求接口进行细化,保持接口的纯洁。
        • 总结:建立单一接口,接口不要过分臃肿。接口要尽量细化,接口中要尽量少。
    • 接口隔离原则和单一职责原则
      • 明确单一职责原则是按照职责单一,是从业务逻辑角度来看。
      • 明确接口隔离原则是要求接口的方法要尽量的少。

    ISP举例

    聚合关系:空心棱形箭头,全体和部分的关系,与组合关系的区别是:组合关系彼此依靠,缺一不可,而聚合关系彼此之间是可以独立存在的。最明显的例子:人和车,人可以拥有车,但是不是必须的。车与轮子之间的关系:车必须拥有轮子。

    • 给出星探寻找美女的类图

    file

    • 具体实现代码

    • 美女抽象接口:定了美女的标准

        package des.ISP;
        //美女抽象类public 
        interface IPrettyGirl {    
        //较好的面容    
        public void goodLooking();    
        //要有好的身材    
        public void niceFigure();    
        //要有气质    
        public void greatTemmperament();
        }
    
    • 美女实现类
    package des.ISP;
    //美女实现类
    public class PrettyGirl implements IPrettyGirl {
        //名字
        private String  name;
        public  PrettyGirl(String name){
            this.name = name;
    
        }
        @Override
        public void goodLooking() {
            System.out.println("拥有较好的面貌");
    
        }
    
        @Override
        public void niceFigure() {
            System.out.println("拥有较好的身材");
        }
    
        @Override
        public void greatTemmperament() {
            System.out.println("拥有较好的气质");
        }
    }
    
    • 抽象星探类
    package des.ISP;
    
    public abstract class AbstractSearcher {
        protected IPrettyGirl prettyGirl;
        public AbstractSearcher(IPrettyGirl _prettyGirl){
            this.prettyGirl = _prettyGirl;
        }
        //搜索美女,列出美女列表
        public abstract void show();
    }
    
    
    • 具体实现类
    package des.ISP;
    
    public class Searcher extends AbstractSearcher {
        public Searcher(IPrettyGirl _prettyGirl) {
            super(_prettyGirl);
        }
        //展示美女的信息
        @Override
        public void show() {
            System.out.println("美女信息如下...");
            
            //展示面容
            super.prettyGirl.goodLooking();
            //展示气质
            super.prettyGirl.greatTemmperament();
            //展示气质
            super.prettyGirl.niceFigure();;
        }
    }
    
    

    运行结果:
    file


    我们看IPrettyGirl接口是否设计的合理?合理是相对的,我们如果从另外一个角度来看,对于美女的标准定义不同,比如一个人的气质很好,我们也可以称为美女,另外一个人的身材和外貌很美那我们也可以称位气质。从一定程度上来看,我们定义的这个接口是否太过臃肿了?里面存在很多可变的因素,比如只有气质很好,我们也可以称作美女。这样我们必须要将剩下的两个方法置空,这样做的目的肯定是不行的。
    首先我们将,美女接口进行分解,分解为气质型和外表型,那么标准的美女就是同时实现这两个接口,那么气质型和外表型就分别实现这两个接口。
    file
    改写后的代码如下:

    package des.ISP;
    
    public interface IGreatTemperamentGirl {
        //要有气质
        public void greatTemmperament();
    }
    
    package des.ISP;
    //外貌美女
    public interface IGoodBodyGirl {
        //较好的面容
        public void goodLooking();
        //要有好的身材
        public void niceFigure();
    }
    
    
    package des.ISP;
    //美女实现类
    public class PrettyGirl implements IGoodBodyGirl,IGreatTemperamentGirl {
        //名字
        private String  name;
        public  PrettyGirl(String name){
            this.name = name;
    
        }
        @Override
        public void goodLooking() {
            System.out.println(this.name+"拥有较好的面貌");
    
        }
    
        @Override
        public void niceFigure() {
            System.out.println(this.name+"拥有较好的身材");
        }
    
        @Override
        public void greatTemmperament() {
            System.out.println(this.name+"拥有较好的气质");
        }
    }
    
    
    package des.ISP;
    
    public abstract class AbstractSearcher {
        protected IGoodBodyGirl iGoodBodyGirl;
        protected IGreatTemperamentGirl iGreatTemperamentGirl;
        public AbstractSearcher(IGoodBodyGirl _goodBodyGirl){
            this.iGoodBodyGirl = _goodBodyGirl;
        }
        public AbstractSearcher(IGreatTemperamentGirl _iGreatTemperamentGirl){
            this.iGreatTemperamentGirl = _iGreatTemperamentGirl;
        }
        //搜索美女,列出美女列表
        public abstract void show();
    }
    
    
    package des.ISP;
    
    public class Searcher extends AbstractSearcher {
    
        public Searcher(IGoodBodyGirl _goodBodyGirl) {
            super(_goodBodyGirl);
        }
        public Searcher(IGreatTemperamentGirl _iGreatTemperamentGirl) {
            super(_iGreatTemperamentGirl);
        }
    
    
    
        @Override
        public void show() {
            super.iGoodBodyGirl.goodLooking();
            super.iGoodBodyGirl.niceFigure();
            super.iGreatTemperamentGirl.greatTemmperament();
        }
    }
    
    

    此时存在的问题:场景类的写法,由于我们PrettyGirl是实现的两个接口,并且在星探类中采用的两个入参为抽象接口的构造方法,所以上面的写法只是对于两种不同类型的即气质型和外形两种,假如即是气质型和外形好的的话,我们要在星探抽象类再增加一个构造方法,此时入参为具体的实现类(此时入参不要再考虑依赖倒置原则,因为这些应用原则不是绝对使用,方便使用就用,不方便用不用即可。)
    综述:上述的改进是对接口中可变的因素的细化的拆分,具体的实现代码是参考,只需明白UML表达的意思即可,即接口中的方法不能过分臃肿,否则一旦存在可变因素,接口耦合性就会变高。

  • 相关阅读:
    TMainMenu 类 手动建立菜单 : 指定快捷键《转》
    确定多重选择列表控件 (List Control) 中的选定内容
    【320K】大峡谷The Music of The Grand Canyon
    35种音乐的分类
    ASP中常用的变量命名规则
    关于DBF文件导入问题
    ASP.NET里的变量命名规则
    ASP中数据库安全问题之我见
    用err.raise自定义错误信息
    关于编程风格的讨论 PioneerMan(原作)
  • 原文地址:https://www.cnblogs.com/quinntian/p/10745621.html
Copyright © 2011-2022 走看看