1. 程式人生 > >第1章:策略模式

第1章:策略模式

rate 部分 方案 pattern 應用場景 繼承 方法 rmq play

1 策略模式

策略模式定義了算法族分別封裝起來,讓他們之間可以相互替換(實現接口),此模式讓算法的變化獨立於使用算法的客戶(組合+委托)

1.1 應用場景

需要方法的實現獨立於客戶端代碼,即保證客戶端代碼不變前提下,方法具體執行內容可以任意更換

Duck mallardDuck = new MallardDuck();
//下方代碼後,該語句的調用產生不同的結果,即算法間的相互替換
mallardDuck.setFlyBehavior(new FlyNoWay());
mallardDuck.performFly();

1.2 錯誤解決方案

1.2.1 父類中直接增加方法
package strategy.pattern;

public abstract class Duck1 {
    //組合解決的問題
    //1.所有Duck1中,不會飛或不是quack這麽叫的鴨子,都需要重寫下面方法,這樣重復代碼太多,不利於維護
    
    //策略模式解決的問題
    //2.客戶端調用同一個類型的子類對象的該方法結果是固定的,例如創建一個Duck1子類,該對象無法完成一會可以飛,一會不能飛
    public void fly(){
        System.out.println("I can fly");
    }
    public void quack(){
        System.out.println("quack");
    }
}
1.2.2 不同子類實現不同包含方法的接口,並重寫該方法

FlyBehavior接口中定義抽象方法fly,所有鴨子實現該接口,並重寫fly方法,與上面缺點相同

1.3 解決思路

1.3.1 分開變化和不會變化的部分

==設計原則:找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起==

  1. 分析該問題中,fly與quack對於不同的鴨子子類,行為是不同的,因此應該將該方法的具體實現與鴨子類本身分離開
  2. Duck2
package strategy.pattern;

public abstract class Duck2 {
    Quack quack = new Quack();
    FlyWithWings flyWithWings = new FlyWithWings();
    public void fly(){
        //具體的實現在Quack和FlyWithWings中定義,達到了和Duck2及其子類的分離
        flyWithWings.fly();
    }
    public void quack(){
        quack.quack();
    }
}
1.3.2 面向接口編程

==設計原則:針對接口編程,而不是針對實現編程==

==設計原則:多用組合少用繼承==

  1. 之前無法動態地指定鴨子子類的行為,也無法為特定鴨子子類指定特定行為
  2. Duck3
package strategy.pattern;

public abstract class Duck3 {
    //1.QuackBehavior、FlyBehavior為接口,此處為面向接口編程
    //使用組合解決了繼承帶來的代碼重復問題
    QuackBehavior quack;
    FlyBehavior flyWithWings;
    public void fly(){
        //執行的是flyWithWings變量指向的真正的對象的fly方法
        flyWithWings.fly();
    }
    public void quack(){
        quack.quack();
    }
    //2.可以指定具體行為對應類,可以動態的指定鴨子子類的行為,也可以為特定鴨子子類指定特定行為
    public void setQuack(QuackBehavior quack) {
        this.quack = quack;
    }
    public void setFlyWithWings(FlyBehavior flyWithWings) {
        this.flyWithWings = flyWithWings;
    }
}

1.4 類圖

技術分享圖片

1.5 代碼

  1. FlyBehavior:接口
package strategy.pattern;

public interface FlyBehavior {
    void fly();
}
  1. FlyNoWay:實現類
package strategy.pattern;

public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("I cant fly");
    }
}
  1. FlyWithWings:實現類
package strategy.pattern;

public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("I'm flying");
    }
}
  1. QuackBehavior:接口
package strategy.pattern;

public interface QuackBehavior {
    void quack();
}
  1. Quack:實現類
package strategy.pattern;

public class Quack implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Quack");
    }
}
  1. Squeak:實現類
package strategy.pattern;

public class Squeak implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Squeak");
    }
}
  1. MuteQuack:實現類
package strategy.pattern;

public class MuteQuack implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Silence");
    }
}
  1. Duck
package strategy.pattern;

public abstract class Duck {
    //使用策略模式實現鴨子的各種行為,即鴨子的行為封裝在一組類中,可以輕易的擴充與改變
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
    public abstract void display();
    public void swim(){
        System.out.println("All ducks float,even decoys");
    }
    public void performFly(){
        flyBehavior.fly();
    }
    public void performQuack(){
        quackBehavior.quack();
    }
    //提供兩個set方法,可以動態修改鴨子的行為
    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
}
  1. MallardDuck:綠頭鴨,Duck的一個實現類
package strategy.pattern;

public class MallardDuck extends Duck{
    @Override
    public void display() {
        System.out.println("I'm a real Mallard duck");
    }
    //初始化時,順便初始化綠頭鴨的所有行為
    public MallardDuck(){
        flyBehavior = new FlyWithWings();
        quackBehavior = new Quack();
    }
}
  1. MallarDuckSimulator:測試類
package strategy.pattern;

public class MallarDuckSimulator {
    public static void main(String[] args) {
        Duck mallardDuck = new MallardDuck();
        mallardDuck.performFly();
        mallardDuck.performQuack();
        mallardDuck.setFlyBehavior(new FlyNoWay());
        //前後同一個對象mallardDuck調用同一個方法performFly,打印的內容不同,即可以在運行時改變行為
        mallardDuck.performFly();
    }
}

第1章:策略模式