连载:面向对象葵花宝典:思想、技巧与实践(33) - ISP原则

 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.”

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

单纯从字面意思来看,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原则建议客户端不需要知道整个类,只需要知道具有内聚接口的抽象父类即可。

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

虽然翻译了一下,但还是比较抽象,给个例子一看就明白了,而且已经有一个很好的例子了,即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接口,
    }
}

连载:面向对象葵花宝典:思想、技巧与实践(33) - ISP原则,布布扣,bubuko.com

时间: 2024-11-05 12:20:14

连载:面向对象葵花宝典:思想、技巧与实践(33) - ISP原则的相关文章

连载:面向对象葵花宝典:思想、技巧与实践(34) - DIP原则

DIP,dependency inversion principle,中文翻译为"依赖倒置原则". DIP是大名鼎鼎的Martin大师提出来的,他在1996 5月的C++ Reporter发表" The Dependency Inversion Principle"的文章详细阐述了DIP原则,并且在他的经典著作< Agile Software Development, Principles, Patterns>(中文翻译为:敏捷软件开发:原则.模式与实践

连载:面向对象葵花宝典:思想、技巧与实践(32) - LSP原则

LSP是唯一一个以人名命名的设计原则,并且作者还是一个"女博士"  ============================================================= LSP,Liskov substitution principle,中文翻译为"里氏替换原则". 这是面向对象原则中唯一一个以人名命名的原则,尽管Liskov在中国的知名度没有UNIX的几位巨匠(Kenneth Thompson.Dennis Ritchie).GOF四人帮那么

连载:面向对象葵花宝典:思想、技巧与实践(31) - OCP原则

开闭原则是一个大部分人都知道,但大部分人都不懂的设计原则! ==================================================================== OCP,Open-Closed Principle,中文翻译为"开闭原则". 当我第一次看到OCP原则时,我的感觉就是这原则也太抽象了吧,什么开,什么闭呢? 然后我去寻找更加详细的答案,最经典也是最常见的解释就是维基百科了: http://en.wikipedia.org/wiki/Open

连载:面向对象葵花宝典:思想、技巧与实践(36) - 设计原则如何用?

经过前面深入的阐述,SOLID的原则我们已经基本上讲清楚了,但如果想熟练的应用SOLID原则,仅仅知道SOLID是什么(what)还不够,我们还需要知道SOLID原则在什么时候和什么场景应用(when或where). 幸运的是,SOLID原则的5个独立原则在实际应用中基本上都是独挡一面,并不会在某个地方需要同时从可选的几个原则中挑选一个最优的原则来应用,这样大大降低了我们应用SOLID原则的难度. SOLID原则具体的应用场景如下: SRP原则:用于类的设计 当我们想出一个类,或者设计出一个类的

连载:面向对象葵花宝典:思想、技巧与实践(35) - NOP原则

NOP,No Overdesign Priciple,不要过度设计原则. 这应该是你第一次看到这个原则,而且你也不用上网查了,因为这个不是大师们创造的,而是我创造的:) 之所以提出这个原则,是我自己吃过苦头,也在工作中见很多人吃过类似的苦头. 你可能也见过这样的场景: 产品提出了一个需求,设计师眼光非常长远,他甚至把5年后可能的业务变化都提出来并且加以设计了,让你不得不佩服设计师的高瞻远瞩的眼光,并且由衷的从心底赞叹:牛逼啊! 但很快你就会发现,设计师是很牛逼,但你开发的时候就很苦逼了,设计方案

连载:面向对象葵花宝典:思想、技巧与实践(37) - 设计模式:瑞士军刀 or 锤子?

"设计模式"这个词几乎成为了软件设计的代名词,很多人非常天真的以为掌握了设计模式就掌握了软件设计,但实际上如果只是握了设计模式,软件设计的门都还没摸到! ======================================================== 谈起设计模式,那是几乎无人不知,无人不晓,大名鼎鼎的"GOF"(中文有的翻译为"四人帮")惊世之作,真是"平生不识GOF,学尽设计也枉然!" 然而,设计模式真的是

连载:面向对象葵花宝典:思想、技巧与实践(39) - 设计原则 vs 设计模式

又是设计原则,又是设计模式,到底该用哪个呢? ============================================================================= 在"设计模型"一章中,我们提到设计原则和设计模式是互补的,设计原则和设计模式互补体现在:设计原则主要用于指导"类的定义"的设计,而设计模式主要用于指导"类的行为"的设计. 举一个很简单的例子:假设我们要设计一个图形类Shape,这个类既支持三角形,

连载:面向对象葵花宝典:思想、技巧与实践(29) - 高内聚低耦合

高内聚低耦合,可以说是每个程序猿,甚至是编过程序,或者仅仅只是在大学里面学过计算机,都知道的一个简单的设计原则. 虽然如此流行和人所众知,但其实真正理解的人并不多,很多时候都是人云亦云. =============================================================== 要想真正理解"高内聚低耦合",需要回答两个问题: 1)为什么要高内聚低耦合? 2)高内聚低耦合是否意味内聚越高越好,耦合越低越好? 第一个问题:为什么要高内聚低耦合? 经典的

连载:面向对象葵花宝典:思想、技巧与实践(38) - 设计模式之道

很多人能够熟练背诵出所有的设计模式,能够快速画出各种设计模式的UML类图,也能够熟练的写出<设计模式>一书中各个模式的样例代码.但一到实际的项目设计和开发的时候,往往都会陷入迷茫:要么无从下手,不知道哪个地方要用设计模式:要么生搬硬套,胡乱使用设计模式,将方案和代码搞得一团乱麻. =========================================================================== [知易行难 -- 设计模式应用的问题] 形而下者谓之器,形而上者