接口有何用?面試寶典上背下來的總結,你真的明白嗎?
接口&工廠方法 其實很簡單>。<~
什么是接口
先看看生活中的接口,比如USB接口。
USB接口的設計者在最初就知道USB能支持這么多功能嗎?他們是怎
樣未卜先知地設計的呢?其實他們也不知道以后USB上會連什么設
備,他們只是定義了一個數據傳輸與供電的標準而已。
java中也是類似的,定義了接口,就等于定義了調用對象的標準。
接口的基本語法
使用 interface定義;
接口當中的方法都是抽象方法;
接口當中的方法都是public權限(接口中的方法,寫不寫public修飾
符,都是public權限,別的地方不行哦);
可以把接口理解成一個更加純粹的抽象類,因此它也不能生成對象。
這要怎么辦呢?回想抽象類的處理方法,可以用一個類來繼承(接口
中叫實現)它,從而在子類中生成對象。
一個最簡單的接口示例:
定義一個接口:
interface USB { public void read(); public void write();}定義它的子類,來實現這個接口:
class Phone implements USB { public void read() { System.out.測試:class Test { public static void main(String args []) { Phone phone = new Phone(); //向上轉型 USB usb = phone; usb.read(); usb.write(); }}運行結果: 圖片描述 繼續了解接口的語法:
實現接口使用implements關鍵字;
一個類可以實現多個接口;
實現是特殊的繼承,換句話說,就是一個類可以繼承多個接口。
修改上面的代碼: 再定義一個WiFi接口:
interface WiFi { public void open(); public void close();}讓Phone也實現WiFi接口:
class Phone implements USB, WiFi { public void read() { System.out.println("Phone --> Reading"); } public void write() { System.out.println("Phone --> Writing"); } //實現WiFi中的抽象方法 public void open() { System.out.println("WiFi --> Open"); } public void close() { System.out.println("WiFi --> Close"); } }測試一下:
class Test { public static void main(String args []) { Phone phone = new Phone(); //向上轉型時,就有兩種選擇 USB usb = phone; usb.read(); usb.write(); WiFi wifi = phone; wifi.open(); wifi.close(); }}運行結果: 圖片描述
可以看到,用USB連接手機時,手機表現的就是USB的行為,用WiFi
連接手機時,手機表現的就是WiFi的行為,這也是面向對象多態性非
常明顯的體現。
一個接口可以繼承多個接口
注意這里不能寫成implements,因為我們只想繼承USB和WiFi接口
的抽象方法,而不想實現它。
interface SbFi extends USB, WiFi { public void piu();}這樣SbFi接口就擁有read(),write(),open(),close()和piu()五個抽象方法了:) 接口的實踐
如果我們接到一個客戶的需求,用程序控制辦公室中的打印機,我們
該怎么做呢?容易想到,先用一個類描述“打印機”,再用一些方法
實現“開機”、“關機”、“打印”等動作,一個簡單的Printer類就能搞定了。 可是如果客戶提出了新的需求,辦公室又買了一臺其他品牌的打印
機,讓你修改之前的代碼。這時要怎么做呢?都是打印機,只是品牌
不同,功能略有差異,容易想到用接口或者繼承。接口更靈活一些,
所以我們寫出了下面的代碼:
首先定義一個Printer接口,描述打印機都有的行為:
interface Printer { void open(); void print(String s); void close();}在惠普打印機類中,實現Printer中的抽象方法:
class HPPrinter implements Printer { public void open() { System.out.println("HP: open"); } public void print(String s) { System.out.println("HP: print--> " + s); } public void close() { System.out.println("HP: close"); }}在佳能打印機中,又增加了新的方法,清洗:
public class CanonPrinter implements Printer { public void open() { System.out.println("Canon: open"); } public void print(String s) { System.out.println("Canon: print-->" + s); } public void close() { this.clean(); System.out.println("Canon: close"); } public void clean() { System.out.println("Canon: clean"); }}測試: 注意,這里使用對象的向上轉型,能減少重復代碼。不然就得用
HPPrinter和CanonPrinter生成的對象分別調用open, print, close方
法,很麻煩。如果以后有100臺打印機,豈不是得寫300行?
class Test { public static void main(String args []) { Printer printer = null; //為簡便,flag模擬用戶選擇使用哪臺打印機 int flag = 1; if(flag == 0) { //向上轉型 printer = new HPPrinter(); } else if(flag == 1) { printer = new CanonPrinter(); } printer.open(); printer.print("向上轉型好用吧~"); printer.close(); }}運行: 圖片描述
大功告成。但是這樣就足夠了嗎?
如果我們的打印機代碼,是在一個辦公自動化的系統當中。可能有各
種各樣的功能,要使用打印機。那每次使用時,都要把Test類中的這
一段寫一遍嗎?如果以后有100個地方要用,豈不是要把這一段寫
100次?更可怕的是,如果又添加了新的打印機,豈不是要修改這
100段代碼?太容易出錯了。所以,我們和重復代碼,是勢不兩立的
(振臂一呼)!
進擊的工廠方法模式
減少重復代碼的一般方法就是,把重復的代碼放在一個地方(封裝起
來),等要用的時候,就調用它,而不是再寫一遍。仔細看Test類,
重復的地方,不包括最后三行,主要是根據用戶的選擇,生成打印機
對象,并向上轉型為Printer類型的部分。
我們可以設計一個類,在里面添加一個函數,它的功能就是根據用戶
的選擇生成打印機對象,以后我們直接調用這個函數就行了。函數的
參數,就是用戶的選擇,返回值,就是一個Printer類型的對象。
class PrinterFactory { //添加static是為了調用方便 public static Printer getPrinter(int flag) { Printer printer = null; if(flag == 0) { printer = new HPPrinter(); } else if(flag == 1) { printer = new CanonPrinter(); } return printer; } }class Test { public static void main(String args []) { int flag = 1; Printer printer = PrinterFactory.getPrinter(flag); printer.open(); printer.print("對象的轉型好用吧~"); printer.close(); }}這樣,就算要增加100臺打印機,也只用在PrinterFactory中添加
else if(flag == xxx) 的代碼,不用修改Test類。
這就是著名的簡單靜態工廠方法模式。
PrinterFactory并不關心Printer類有多少個子類,這樣我們就能夠自由地修改Printer子類了。
工廠方法模式的思路很簡單,就是把生成對象的代碼,封裝在工廠類當中。
新聞熱點
疑難解答