zoukankan      html  css  js  c++  java
  • 连载:面向对象葵花宝典:思想、技巧与实践(33)

     ISP,Interface Segregation Principle,中文翻译为“接口隔离原则


    和DIP原则一样,ISP原则也是大名鼎鼎的Martin大师提出来的,他在1996年的C++ Reporter发表“ The Interface Segregation Principle”的文章具体阐述了ISP原则,并且在他的经典著作《 Agile Software Development, Principles, Patterns》(中文翻译为:敏捷软件开发:原则、模式与实践)、《Practices, and Agile Principles, Patterns, and Practices in C#》(中文翻译为:敏捷软件开发:原则、模式与实践(C#版))中详解了ISP原则。

     

    ISP最原始的定义例如以下:

    “CLIENTS SHOULD NOT BE FORCED TO DEPEND UPON INTERFACES THAT THEY DO NOT USE.”

    翻译成中文就是“client不应该被强迫去依赖它们并不须要的接口”。

     

    单纯从字面意思来看,ISP原则是5个原则中最好理解的一个了。可是我们深入思考一下,事实上发现也没有那么简单。假设你还记得我们前面讲的那些原则,你可能会想到一个问题:既然有了SRP,为什么还要ISP?

     

    如今我们来回忆一下SRP原则,假设类满足了SRP原则,那么基于这个类提炼的接口不就自然而然的满足了ISP原则了么?为什么我们还要费神费力的又搞一个ISP原则呢?

     

    Martin大师自然不会是吃饱了没事做,有益整个东东来折腾大家,他在ISP的论文中有这么一句话交代了ISP原则,可惜的是非常多人都没有把这句话贴出来:

    The ISP acknowledges that there are objects that require non-cohesive interfaces;

    however it suggests that clients should not know about them as a single class. Instead, clients

    should know about abstract base classes that have cohesive interfaces.

    翻译一下:ISP原则承认对象须要非内聚的接口,然而ISP原则建议client不须要知道整个类,仅仅须要知道具有内聚接口的抽象父类就可以。

     

    也就是说,ISP应用的场景是某些类不满足SRP原则,但使用这些类的client(即调用的类)应该依据接口来使用它,而不是直接使用它

     

    尽管翻译了一下,但还是比較抽象,给个样例一看就明确了,并且已经有一个非常好的样例了,即SRP原则中的“一体机”。

     

    在“一体机”的样例中,尽管“一体机”同一时候具备“打印、复印、扫描、传真”的功能,但我们并不会设计一个“一体机”的接口,而是设计4个接口。这样调用接口的类能够依据自己须要精确使用某个接口,而不是调用一个大而全的接口。

     

    具体代码例如以下:

    ICopier.java

    package com.oo.java.principles.isp;
    
    /**
     * 复印机接口
     */
    public interface ICopier {
        
        /**
         * 复印
         * @param paper
         */
        void copy(Paper paper);
    }


    IFaxMachine.java

    package com.oo.java.principles.isp;
    
    /**
     * 传真机接口
     */
    public interface IFaxMachine {
    
        /**
         * 传真
         * @param msg
         */
        void fax(String msg);
    }

    IPrinter.java

    package com.oo.java.principles.isp;
    
    /**
     * 打印机接口
     */
    public interface IPrinter {
        
        /**
         * 打印
         * @param doc
         */
        void print(Document doc);
    }
    

    IScanner.java

    package com.oo.java.principles.isp;
    
    /**
     * 扫描仪接口
     */
    public interface IScanner {
    
        /**
         * 扫描
         * @param paper
         */
        void scan(Paper paper);
    }
    

    MultiFuncPrinter.java

    package com.oo.java.principles.isp;
    
    /**
     * 多功能打印机(一体机)
     * 实现了IFaxMachine(传真机)、ICopier(复印机)、IPrinter(打印机)、IScanner(扫描仪)4个接口
     * 而不是提供一个IMultiFuncPrinter的接口,同一时候提供以上接口的功能
     *
     */
    public class MultiFuncPrinter implements IFaxMachine, ICopier, IPrinter, IScanner {
    
        @Override
        public void scan(Paper paper) {
            // TODO Auto-generated method stub
        }
    
        @Override
        public void print(Document doc) {
            // TODO Auto-generated method stub
        }
    
        @Override
        public void copy(Paper paper) {
            // TODO Auto-generated method stub
        }
    
        @Override
        public void fax(String msg) {
            // TODO Auto-generated method stub
        }
    }
    

    People.java

    package com.oo.java.principles.isp;
    
    /**
     * 人
     */
    public class People {
        
        /**
         * 复印操作,copy方法依赖ICopier接口,而不是使用MutiFuncPrinter类
         */
        public void copy(ICopier copier, Paper paper){
            copier.copy(paper);
        }
        
        /**
         * 打印操作,print方法依赖IPrinter接口,而不是使用MutiFuncPrinter类
         */
        public void print(IPrinter printer, Document doc){
            printer.print(doc);
        }
        
        /**
         * 传真操作,fax方法依赖IFaxMachine接口,而不是使用MutiFuncPrinter类
         */
        public void fax(IFaxMachine faxer, String message){
            faxer.fax(message);
        }
        
        /**
         * 扫描操作,scan方法依赖IScanner接口,而不是使用MutiFuncPrinter类
         */
        public void scan(IScanner scanner, Paper paper){
            scanner.scan(paper);
        }
    }
    

    Tester.java

    package com.oo.java.principles.isp;
    
    public class Tester {
    
        public static void mai(String args[]){
            People people = new People();
            MultiFuncPrinter mfp = new MultiFuncPrinter();
            
            //例如以下函数都是使用mfp作为參数,但实际上是使用了MultiFuncPrinter类实现了的不同接口
            people.copy(mfp, new Paper());     //使用了MultiFuncPrinter类的ICopier接口,
            people.fax(mfp, "I love oo");      //使用了MultiFuncPrinter类的IFaxMachine接口,
            people.print(mfp, new Document()); //使用了MultiFuncPrinter类的IPrinter接口,
            people.scan(mfp, new Paper());     //使用了MultiFuncPrinter类的IScanner接口,
        }
    }
    





  • 相关阅读:
    言多必失失在哪?
    C/C++四种方法实现加法操作_艾孜尔江撰
    VS Code添加到右键菜单_艾孜尔江撰
    网页端UVC相机测试_艾孜尔江撰
    Python爬虫示例
    Java制作软光栅化渲染器_艾孜尔江撰
    指针常量与常量指针
    C/C++中Main之后执行的函数_艾孜尔江撰
    Token机制 ——JSON Web Token(JWT)的详解
    Excel-实现隔行设置背景色
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/3856118.html
Copyright © 2011-2022 走看看