一、什么是面向接口編程
要正確地使用Java語言進行面向對象的編程,從而提高程序的復用性,增加程序的可維護性、可擴展性,就必須是面向接口的編程。面向接口的編程就意味著:開發系統時,主體構架使用接口,接口構成系統的骨架。這樣就可以通過更換實現接口的類來更換系統的實現。
例如:在上節示例中,Java接口Introduceable就是系統骨架的一個重要組成部分,這個Java接口定義了一個方法:detailo中心類和教員類分別實現了Java接口Introduceable,因此具有了不同的detail方法實現。在School2類中,print方法接收的參數類型是Introduceable,這樣,就可以向print方法傳遞任意一個Introduceable接口的實現類,在運行時,Java虛擬機會根據實際創建的對象類型調用不同的方法實現。這就意味著:可以通過更換實現接口的類來更換系統的實現。
二、面向接口編程的示例
接下來通過一個示例詳細講解面向接口編程的實現過程。
案例需求的效果圖如圖1所示。
升級系統,要求如下:
★ 打印機有多種類型,比如:黑白打印機、彩色打印機等。
★ 中心可能配備其中任意一款打印機,負責打印教員或者中心的詳細信息。
★ 系統要具備良好的可擴展性與可維護性。
圖1 使用不同類型的打印機進行打印
采用面向接口編程的方式實現可以分為3個步驟。
1.抽象出Java接口
分析:由于黑白、彩色打印機都存在一個共同的方法特征:print,而且黑白、彩色打印機對print方法有各自不同的實現,因此可以抽象出一個Java接口PrinterFace(代表打印機),在其中定義print方法。
具體實現代碼如下:
折疊
Java 代碼
package?Java.sg.ch03;
publicinterfacePrinterFace?{
//定義打印方法
publicvoicl?print?(String?content);
}
2.實現Java接口
分析:在第一步中已經抽象出Java接口PrinterFace,并在其中定義了print方法。由于黑白、彩色打印機對print方法有各自不同的實現,因此在第2步中,要讓黑白、彩色打印機實現PrinterFace接口,各自實現print方法。
彩色打印機代碼實現如下:
折疊
Java 代碼
package?Java.sg.ch03;
publicclassColorPrinterimplements
PrinterFace?{
/**
*?打印方法
*/
publicvoidprint(String?content)?{
System.out.println("彩色打印?:");
System.out.println(content);
}
}
黑白打印機代碼實現如下:
折疊
Java 代碼
package?Java.sg.ch03;
publicclassBlackPrinterimplements
PrinterFace?{
/**
*?打印方法
*/
publicvoidprint(String?content)?{
System.out.println("黑白打印?:");
System.out.println(content);
}
}
3.使用Java接口
經驗:現在,Java接口及其實現類都已經創建完畢,接著,我們就要使用面向接口編程的原則,讓接口構成系統的骨架,以便達到更換實現接口的類就可以更換系統的實現的目的。
中心類負責對外提供打印功能,要求可以隨時更換打印機類型。代碼實現如下:
折疊
Java 代碼
package?Java.sg.ch03;
publicclassSchool3implementsIntroduceable{
privatePrinterFace?printer;//打印機
//??輸出中心的詳細信息
publicString?detail()?{
return"這里是中心";
}
//??使用中心打印機打印信息
publicvoidprint(Introduceable?intro){
printer.print(intro.detail());
}
//設置打印機
publicvoidsetPrinter(PrinterFace?p)?{
this.printer?=?p;
}
}
測試類提供main方法進行單元測試。代碼實現如下:
折疊
Java 代碼
/*
*?jsp.sg.ch04.Test.java
*?2011-5-29
*?4u^j2JavaJavaL
*/
packageJava.sg.ch03;
publicclassTest?{
publicstaticvoidmain(String[]?args)?{
//創建中心實例
School3?school?=newSchool3();
//為該中心配備黑白打印機
school.setPrinter(newBlackPrinter());
school.print(school);
//為該中心配備彩色打印機
school.setPrinter(newColorPrinter());
school.print(school);
}
}
經驗:面向接口編程可以實現接口和實現的分離,這樣做的最大好處就是能夠在客戶端未知的情況下修改實現代碼。那么什么時候應該抽象出Java接口呢?一種是用在層和層之問的調用。層和層之間是最忌諱耦合度過高或是改變過于頻繁。設計優秀的接口能夠解決這個問題。另一種是用在那些不穩定的部分上。如果某些需求的變化性很大,那么定義接口也是一種解決之道。設計良好的接口就像是我們日常使用的萬用插座一樣,不論插頭如何變化,都可以使用。
最后強調一點,良好的接口定義一定是來自于需求的,它絕對不是程序員絞盡腦汁想出來的。