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