Java 介面——面向對象的精髓
介面有何用?面試寶典上背下來的總結,你真的明白嗎?
介面&工廠方法 其實很簡單>。
什麼是介面
先看看生活中的介面,比如USB介面。
USB介面的設計者在最初就知道USB能支持這麼多功能嗎?他們是怎樣未卜先知地設計的呢?其實他們也不知道以後USB上會連什麼設備,他們只是定義了一個數據傳輸與供電的標準而已。
Java中也是類似的,定義了介面,就等於定義了調用對象的標準。
介面的基本語法
使用 interface定義;
介面當中的方法都是抽象方法;
介面當中的方法都是public許可權(介面中的方法,寫不寫public修飾符,都是public許可權,別的地方不行哦);
可以把介面理解成一個更加純粹的抽象類,因此它也不能生成對象。這要怎麼辦呢?回想抽象類的處理方法,可以用一個類來繼承(介面中叫實現)它,從而在子類中生成對象。
一個最簡單的介面示例:
定義一個介面:
interface USB {
public void read();
public void write();
}
定義它的子類,來實現這個介面:
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中的抽象方法:
}
測試:
注意,這裡使用對象的向上轉型,能減少重複代碼。不然就得用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子類了。
工廠方法模式的思路很簡單,就是把生成對象的代碼,封裝在工廠類當中。
點擊展開全文
※掃碼登錄的安全性分析
※Java程序員面試的5 點小技巧
※Junit4使用學習-初步教程
※Java常犯5個錯!
TAG:java學習吧 |
※Lua 面向對象
※Perl 面向對象
※面向不同需求的對象存儲系統對比:Ceph與Swift
※Python指南:面向對象程序設計
※Python入門基礎之面向對象四:運算符重載
※AppleCare+ for Mac正式面向中國市場推出
※蘋果AppleCare+for Mac正式面向中國市場推出
※華為面向西歐市場正式推出融合快閃記憶體陣列OceanStor V5
※谷歌 I/O 開發者大會上的 Smart Compose 功能開始面向 Gmail 桌面用戶公測
※Mentor面向智能家居的IoT方案
※Unity 編輯器現已正式面向 Linux 推出
※TensorFlow官方最新tf.keras指南:面向對象構建深度網路
※面向 JS 開發者的機器學習框架 TensorFlow.js 以及相關示例
※出門問問發布面向企業場景的智能交互屏TicKasa Show
※華為聯合Purple發布面向商業的精準營銷解決方案
※谷歌宣布進一步擴大面向黑人工程師的Howard West項目
※微軟面向醫療機構推出Healthcare Bot服務
※Python面向對象之魔法方法/雙下方法
※Fitbit面向合作夥伴推出Inspire健身追蹤器 概不零
※OmniVision宣布推出OVMed?圖像信號處理器,面向醫療和工業內窺鏡應用