title: 策略模式
date: 2016-07-18 21:10:26
tags: 編程
categories: 設計模式
策略模式定義 定義了算法簇,分別封裝起來,讓他們之間可以互相替代,此模式讓算法的變化獨立于使用算法的客戶
策略模式的作用
完成一項任務,往往可以有多種不同的方式,每一種方式稱為一個策略,我們可以根據環境或者條件的不同選擇不同的策略來完成該項任務。
在軟件開發中也常常遇到類似的情況,實現某一個功能有多個途徑,此時可以使用一種設計模式來使得系統可以靈活地選擇解決途徑,也能夠方便地增加新的解決途徑。
在軟件系統中,有許多算法可以實現某一功能,如查找、排序等,一種常用的方法是硬編碼(Hard Coding)在一個類中,如需要提供多種查找算法,可以將這些算法寫到一個類中,在該類中提供多個方法,每一個方法對應一個具體的查找算法;當然也可以將這些查找算法封裝在一個統一的方法中,通過if…else…等條件判斷語句來進行選擇。這兩種實現方法我們都可以稱之為硬編碼,如果需要增加一種新的查找算法,需要修改封裝算法類的源代碼;更換查找算法,也需要修改客戶端調用代碼。在這個算法類中封裝了大量查找算法,該類代碼將較復雜,維護較為困難。
除了提供專門的查找算法類之外,還可以在客戶端程序中直接包含算法代碼,這種做法更不可取,將導致客戶端程序龐大而且難以維護,如果存在大量可供選擇的算法時問題將變得更加嚴重。
為了解決這些問題,可以定義一些獨立的類來封裝不同的算法,每一個類封裝一個具體的算法,在這里,每一個封裝算法的類我們都可以稱之為策略(Strategy),為了保證這些策略的一致性,一般會用一個抽象的策略類來做算法的定義,而具體每種算法則對應于一個具體策略類。
模式結構
Context: 環境類
Strategy: 抽象策略類
ConcreteStrategy: 具體策略類
時序圖
策略的實現
主函數
package strategymaintest;
public class MiniDuckTest {
public static void main(String[] args) {
Duck duck=new MallardDuck();
duck.performFly();
duck.performQuack();
Duck model=new MallardDuck();
model.performFly();
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
接口和實現類
public interface FlyBehavior {
public void fly();
}
package strategymaintest;
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println(" I am not flying ");
}
}
package strategymaintest;
public class FlyRocketPowered implements FlyBehavior {
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("I am flying with a rocket");
}
}
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("I am flying!!!");
}
}
public interface QoackBehavior {
public void quack();
}
public class Qoack implements QoackBehavior {
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("Qoack");
}
}
package strategymaintest;
public abstract class Duck {
FlyBehavior flyBehavior;
QoackBehavior qoackBehavior;
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQoackBehavior(QoackBehavior qoackBehavior) {
this.qoackBehavior = qoackBehavior;
}
public abstract void display();
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
qoackBehavior.quack();
}
public void swim(){
System.out.println("All ducks float,even decoys!");
}
}
public class MallardDuck extends Duck {
public MallardDuck(){
qoackBehavior=new Qoack();
flyBehavior=new FlyWithWings();
}
public void display(){
System.out.println("I am a real mallard duck");
}
}
package strategymaintest;
public class MiniDuckTest {
public static void main(String[] args) {
Duck duck=new MallardDuck();
duck.performFly();
duck.performQuack();
Duck model=new MallardDuck();
model.performFly();
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
策略的作用
策略模式的重心
策略模式的重心不是如何實現算法,而是如何組織、調用這些算法,從而讓程序結構更靈活,具有更好的維護性和擴展性。
算法的平等性
策略模式一個很大的特點就是各個策略算法的平等性。對于一系列具體的策略算法,大家的地位是完全一樣的,正因為這個平等性,才能實現算法之間可以相互替換。所有的策略算法在實現上也是相互獨立的,相互之間是沒有依賴的。
所以可以這樣描述這一系列策略算法:策略算法是相同行為的不同實現。
運行時策略的唯一性
運行期間,策略模式在每一個時刻只能使用一個具體的策略實現對象,雖然可以動態地在不同的策略實現中切換,但是同時只能使用一個。
公有的行為
經常見到的是,所有的具體策略類都有一些公有的行為。這時候,就應當把這些公有的行為放到共同的抽象策略角色Strategy類里面。當然這時候抽象策略角色必須要用Java抽象類實現,而不能使用接口
參考:《head first 設計模式》