閱讀932 返回首頁    go 阿裏雲 go 技術社區[雲棲]


連載:麵向對象葵花寶典:思想、技巧與實踐(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接口,
    }
}


================================================ 
轉載請注明出處:https://blog.csdn.net/yunhua_lee/article/details/27698945
================================================ 



最後更新:2017-04-03 08:26:19

  上一篇:go 重構機房收費係統之 模板方法模式
  下一篇:go 【端午小練】HDU1021-最簡單的計算機