正文
一、定義
策略模式定義了演算法族,分別封裝起來,讓它們之間可以相互替換,此模式讓演算法的變化獨立於使用演算法的客戶。
要點:
- 策略模式把系統中會變化的部分抽出來封裝。
二、實現步驟
1、建立策略介面
/**
* 策略介面
*/
public interface Strategy {
/**
* 執行策略行為
*/
public void perform();
}
2、建立策略介面的實現類
(1)策略實現類 A
/**
* 策略實現類A
*/
public class StrategyImplA implements Strategy {
/**
* A策略行為
*/
@Override
public void perform() {
System.out.println("perform A...");
}
}
(2)策略實現類 B
/**
* 策略實現類B
*/
public class StrategyImplB implements Strategy {
/**
* B策略行為
*/
@Override
public void perform() {
System.out.println("perform B...");
}
}
3、在使用策略的類中,宣告並使用介面型別的策略變數
/**
* 策略使用者
*/
public class StrategyUser {
/**
* 宣告介面型別的策略變數
*/
private Strategy strategy;
/**
* 通過構造例項化策略
*/
public StrategyUser(Strategy strategy) {
this.strategy = strategy;
}
/**
* 執行策略使用者的行為
*/
public void doBehavior() {
// do something...
// 使用策略
strategy.perform();
// do something...
}
}
4、通過例項化不同的策略實現類,來改變使用者的行為
public class Test {
public static void main(String[] args) {
// 使用策略A
StrategyUser userA = new StrategyUser(new StrategyImplA());
userA.doBehavior();
// 使用策略B
StrategyUser userB = new StrategyUser(new StrategyImplB());
userB.doBehavior();
}
}
三、舉個例子
1、背景
Joe 上班的公司做了一套相當成功的模擬鴨子游戲:SimUDuck。遊戲中會出現各種鴨子,鴨子的種類及屬性如下:
- 種類:綠頭鴨、紅頭鴨、橡皮鴨、誘餌鴨。
- 屬性:外觀、游泳行為、飛行行為、呱呱叫行為(叫聲)。
不同種類的鴨子所對應的屬性如下:
- 綠頭鴨:綠頭鴨的外觀、會游泳、會飛行、呱呱叫。
- 紅頭鴨:紅頭鴨的外觀、會游泳、會飛行、呱呱叫。
- 橡皮鴨:橡皮鴨的外觀、會游泳(漂浮)、不會飛行、吱吱叫。
- 誘餌鴨:誘餌鴨的外觀、會游泳(漂浮)、不會飛行、不會叫。
2、要點
- 由於不同種類的鴨子可能具有不同的飛行行為、呱呱叫行為,因此,可以使用策略模式把這兩種行為抽出來。
3、實現
(1)建立行為介面
/**
* 飛行行為介面
*/
public interface FlyBehavior {
public void fly();
}
/**
* 呱呱叫行為介面
*/
public interface QuackBehavior {
public void quark();
}
(2)實現行為介面
/**
* 用翅膀飛行
*/
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("I'm flying!");
}
}
/**
* 不會飛行
*/
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("I can't flying!");
}
}
/**
* 呱呱叫
*/
public class Quack implements QuackBehavior {
@Override
public void quark() {
System.out.println("Quack");
}
}
/**
* 吱吱叫
*/
public class Squeak implements QuackBehavior {
@Override
public void quark() {
System.out.println("Squeak");
}
}
/**
* 不會叫
*/
public class MuteQuack implements QuackBehavior {
@Override
public void quark() {
System.out.println("<<Silence>>");
}
}
(3)建立鴨子抽象類,並使用行為介面
/**
* 鴨子抽象類
*/
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {
}
/**
* 外觀
*/
public abstract void display();
/**
* 游泳行為
*/
public void swim() {
System.out.println("All ducks float, even decoys!");
}
/**
* 飛行行為
*/
public void performFly() {
flyBehavior.fly();
}
/**
* 呱呱叫行為
*/
public void performQuark() {
quackBehavior.quark();
}
}
(4)建立鴨子子類,並指定具體的行為實現
/**
* 綠頭鴨
*/
public class MallardDuck extends Duck {
public MallardDuck() {
// 指定具體的飛行行為
flyBehavior = new FlyWithWings();
// 指定具體的呱呱叫行為
quackBehavior = new Quack();
}
@Override
public void display() {
System.out.println("I'm a real Mallard duck");
}
}
/**
* 紅頭鴨
*/
public class RedHeadDuck extends Duck {
public RedHeadDuck() {
// 指定具體的飛行行為
flyBehavior = new FlyWithWings();
// 指定具體的呱呱叫行為
quackBehavior = new Quack();
}
@Override
public void display() {
System.out.println("I'm a red head duck");
}
}
/**
* 橡皮鴨
*/
public class RubberDuck extends Duck {
public RubberDuck() {
// 指定具體的飛行行為
flyBehavior = new FlyNoWay();
// 指定具體的呱呱叫行為
quackBehavior = new Squeak();
}
@Override
public void display() {
System.out.println("I'm a rubber duck");
}
}
/**
* 誘餌鴨
*/
public class DecoyDuck extends Duck {
public DecoyDuck() {
// 指定具體的飛行行為
flyBehavior = new FlyNoWay();
// 指定具體的呱呱叫行為
quackBehavior = new MuteQuack();
}
@Override
public void display() {
System.out.println("I'm a decoy duck");
}
}
(5)測試
public class Test {
public static void main(String[] args) {
// 綠頭鴨
MallardDuck mallardDuck = new MallardDuck();
mallardDuck.performFly();
mallardDuck.performQuark();
// 紅頭鴨
RedHeadDuck redHeadDuck = new RedHeadDuck();
redHeadDuck.performFly();
redHeadDuck.performQuark();
// 橡皮鴨
RubberDuck rubberDuck = new RubberDuck();
rubberDuck.performFly();
rubberDuck.performQuark();
// 誘餌鴨
DecoyDuck decoyDuck = new DecoyDuck();
decoyDuck.performFly();
decoyDuck.performQuark();
}
}