一個公司有一款遊戲,鴨子(有很多種類的鴨子)可以有不同的外觀(display函數表示),也可以游泳(swim函數表示),有些鴨子可以飛(fly函數表示)。
方法一:基類Duck定義display,swim,fly三個函數,所有鴨子繼承Duck。問題:如果某種鴨子沒有fly行爲,需要在該類中重寫fly函數,fly(){},麻煩...
方法二:定義接口Flyable,只要擁有fly功能的鴨子就實現這個接口。問題:代碼無法重用,飛行行爲可能有很多種,每次都要自己實現。
設計原則1:找出應用中可能需要變化之處,把他們獨立出來,不要和那些不需要變化的代碼混在一起。
設計原則2:針對接口編程,不要針對實現編程。
前面的兩種做法,第一種行爲來自Duck超類的具體實現,第二種做法繼承某個接口並由之類自行實現而來。這兩種做法都是依賴於“實現”。
我們的設計:定義FlyBehavior的接口,接口中提供fly函數,所有某種特定的fly行爲都作爲一個類實現FlyBehavior這個接口,比如:FlyWithWings、FlyNoWay等。
public interface FlyBehavior{ public void fly(); } public class FlyWithWings implements FlyBehavior{ public void fly(){ System.out.println("I'm flying!"); } } public class MallardDuck extends Duck{ FlyBehavior _flyBehavior; public MallardDuck(){ _flyBehavior = new FlyWithWings(); } public void performFly(){ _flyBehavior.fly(); } }
我們發現,在我們的構造函數中,我們還是在針對實現編程,以後會修正...
設計原則3:多用組合,少用繼承。
良好的OO設計必須具備可複用,可擴充,可維護三個特性。