JAVA中的策略模式


現在我們有一個虛基類-鴨子(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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM