現在我們有一個虛基類-鴨子(abstract Duck). 有真鴨子,野鴨子,橡皮鴨子繼承了該類。虛基類有swing方法,畢竟游泳是所有的鴨子都應有的功能。還有一個虛方法display,這個方法在子類中復寫,畢竟每種鴨子的信息不一樣。
現在我們有新的需求,需要讓我們的鴨子會飛。那么我們可以輕松的想到,在Duck虛基類中增加一個fly方法就行了。但實際上,如果真這么做的話,會讓所有的鴨子都有該功能。而實際上,橡皮鴨是不能飛的!那么,干脆我們不把fly方法寫到基類,而是把fly方法抽象成接口,讓需要該功能的類都實現這個接口。這樣也會有問題,假如我們有更多種類的鴨子怎么辦?我們是不是要為每一個新增的鴨子子類都實現這個接口呢?這樣無疑給我們代碼增加了很多維護成本,也降低了擴展性。
好的,是時候揭曉答案了。我們抽象出一個FlyBehavior接口,然后將各種飛行的方法抽象成不同的類,讓不同的類都實現FlyBehavior借口。然后在我們的Duck虛基類中設置一個FlyBehavior屬性,讓鴨子具有這種功能。當我們在寫子類的時候我們可以動態的決定該子類需要什么樣的Fly方法。
代碼如下:
FlyBehavior接口:
public interface FlyBehavior { void fly(); }
FlyWithWing子類實現FlyBehavior接口。該類代表正常的飛行能力。
public class FlyWithWing implements FlyBehavior { public void fly() { // TODO Auto-generated method stub System.out.println("Fly with wing...."); } }
FlyNoWay子類實現FlyBehavior接口。該類代表沒有飛行能力。
public class FlyNoWay implements FlyBehavior { public void fly() { // TODO Auto-generated method stub System.out.println("Cannot fly."); //throw new Exception("can not fly"); } }
FlyWithRocketPower實現FlyBehavior接口。該類代表鴨子裝上了火箭引擎的飛行能力。
public class FlyWithRocketPower implements FlyBehavior { public void fly() { // TODO Auto-generated method stub System.out.println("Fly with a rocket power on"); } }
Duck虛基類:
public abstract class Duck { private FlyBehavior flyBehavior; public Duck() {} public void fly() { this.flyBehavior.fly(); } public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; } public void swing() { System.out.println("duck is swinging"); } public abstract void display(); }
RealDuck類,繼承了Duck類。真實的鴨子用翅膀飛。
public class RealDuck extends Duck { public RealDuck() { super.setFlyBehavior(new FlyWithWing()); } @Override public void display() { // TODO Auto-generated method stub System.out.println("This is a real duck"); } }
RubberDuck類,繼承了Duck類。橡皮鴨不能飛。
public class RubberDuck extends Duck { public RubberDuck() { super.setFlyBehavior(new FlyNoWay()); } @Override public void display() { // TODO Auto-generated method stub System.out.println("This is a rubber duck. it cannot fly nor quack."); } }
SupperDuck類,繼承了Duck類。超級鴨子能用火箭做動力。
public class SuperDuck extends Duck { public SuperDuck() { super.setFlyBehavior(new FlyWithRocketPower()); } @Override public void display() { // TODO Auto-generated method stub System.out.println("This is a super duck. It can fly with rocket power to the moon."); } }
main函數,測試方法。實例化各種子類,然后還可以動態設置各個鴨子具有的功能。本例中,橡皮鴨一開始不能飛,但后來將其升級為用火箭做動力的鴨子。
public class DuckSimulator { public static void main(String[] args) { Duck realDuck = new RealDuck(); realDuck.fly(); realDuck.display(); System.out.println("============================"); RubberDuck rubberDuck = new RubberDuck(); rubberDuck.fly(); rubberDuck.display(); System.out.println("============================"); SuperDuck superDuck = new SuperDuck(); superDuck.fly(); superDuck.display(); System.out.println("============================"); //upgrade rubber duck to rocket power rubberDuck.setFlyBehavior(new FlyWithRocketPower()); rubberDuck.fly(); } }
輸出結果如下:
Fly with wing....
This is a real duck
============================
Cannot fly.
This is a rubber duck. it cannot fly nor quack.
============================
Fly with a rocket power on
This is a super duck. It can fly with rocket power to the moon.
============================
Fly with a rocket power on