標籤:style blog java color 使用 strong
ISP,Interface Segregation Principle,中文翻譯為“介面隔離原則”。
和DIP原則一樣,ISP原則也是大名鼎鼎的Martin大師提出來的,他在1996年的C++ Reporter發表“ The Interface Segregation Principle”的文章具體闡述了ISP原則,並且在他的經典著作《 Agile Software Development, Principles, Patterns》(中文翻譯為:敏捷式軟體開發 (Agile Software Development):原則、模式與實踐)、《Practices, and Agile Principles, Patterns, and Practices in C#》(中文翻譯為:敏捷式軟體開發 (Agile Software Development):原則、模式與實踐(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介面, }}