iQOO U5 手機入網:50MP 主攝 / 18W 快充,預計搭載天璣 700
實現鴨子的行為
在此,我們有兩個介面,FlyBehavior和QuackBehavior,還有它們對應的類,負責實現具體的行為:
這 樣 的 設 計 , 可 以 讓 飛 行 和 呱 呱 叫 的 動 作 被 其 他的物件複用,因為這些行為已經與鴨子類無關了。而 我 們 可 以 新 增 一 些 行 為 , 不 會 影 響 到 既 有 的 行為類,也不會影響“使用”到飛行行為的鴨子類。 --這麼一來,有了繼承的“複用”好處,卻沒有繼承所帶來的包袱。
整合鴨子的行為
關鍵在於,鴨子現在會將飛行和呱呱叫的動作“委託”(delegate)別人處理,而不是使用定義在Duck類(或子類)內的呱呱叫和飛行方法。
做法是這樣的:
⑴ 首先,在Duck類中“加入兩個例項變數” ,分別為“flyBehavior”與“quack Behavior”,宣告為介面型別(而不是具體類實現型別),每個鴨子物件都會動態地設定這些變數以在執行時引用正確的行為型別(例如:FlyWithWings、Squeak等)。
我們也必須將Duck類與其所有子類中的fly()與quack()刪除,因為這些行為已經被
搬到FlyBehavior與QuackBehavior類中了。
我們用兩個相似的方法performFly()和performQuack()取代Duck類中的fly()與quack()。稍後你就會知道為什麼。
⑵ 現在,我們來實現performQuack():
⑶ 好吧!現在來關心“如何設定flyBehavior與quackBehavior的例項變數”。
看看MallardDuck類:
測試Duck的程式碼
- 輸入並編譯 下面的 D u c k類 ( D u c k . j a v a )以及兩頁前的MallardDuck類(MallardDuck.java)。
public abstract class Duck { //為行為介面型別宣告兩個引用變數,所有鴨子子類(在同一個package中)都繼承它們。 FlyBehavior flyBehavior; QuackBehavior quackBehavior; public Duck() { } /** * 展示 */ public abstract void display(); public void performFly() { flyBehavior.fly(); // 委託給行為類 } public void performQuack() { quackBehavior.quack(); // 委託給行為類 } public void swim() { System.out.println("All duck float, even decoys!"); } public void setFlyBehavior(FlyBehavior fb) { flyBehavior = fb; } public void setQuackBehavior(QuackBehavior qb) { this.quackBehavior = qb; } }
-
輸入並編譯FlyBehavior介面(FlyBehavior.java)與兩個行為實現類(FlyWithWings.java與FlyNoWay.java)。
-
輸入並編譯QuackBehavior介面(QuackBehavior.java)及其三個實現類(Quack.java、MuteQuack.java、Squeak.java) 。
public interface QuackBehavior { void quack(); } ---------------------------------------------------- public class Quack implements QuackBehavior{ @Override public void quack() { System.out.println("Quack"); } } ---------------------------------------------------- public class MuteQuack implements QuackBehavior{ @Override public void quack() { System.out.println("<< Silence >>"); } } ---------------------------------------------------- public class Squeak implements QuackBehavior{ @Override public void quack() { System.out.println("Squeak"); } }
- 輸入並編譯測試類(MiniDuckSimulator.java)
總結
設計原則:封裝變化;多用組合、少用繼承;針對介面程式設計(針對介面程式設計”真正的意思是“針對超型別(supertype)程式設計”),不針對實現程式設計
定義:定義了演算法族,分別封裝起來,讓它們之間可以相互替換,此模式讓演算法的變化獨立於使用演算法的客戶