設計模式第二講--策略模式

小宇渣渣渣發表於2019-01-12

簡介

策略模式屬於用處很多並且很簡單的一種設計模式

在策略模式(Strategy Pattern)中,一個類的行為或其演算法可以在執行時更改。這種型別的設計模式屬於行為型模式。

策略模式中定義了演算法家族,分別封裝起來,讓他們之間可以相互替換,此模式讓演算法的變化,不會影響到使用演算法的客戶。

場景描述

我們再來假設一個場景,根據不同的下訂單入口對使用者進行積分獎勵

app下單使用者 web下單使用者 小程式下單使用者
獎勵100積分 獎勵20積分 獎勵50積分

壞程式碼

package design.pattern.reward;

public class Reward {

    /**
     * 下單平臺 0 web  1 小程式 2 app
     */
    private int platform = 0;

    public Reward(int platform) {
        this.platform = platform;
    }

    /**
     * 給使用者送積分
     */
    public void giveScore() {

        int score = 0;

        switch (platform) {
            case 0: //web
                //todo
                score = 20;
                break;
            case 1: //小程式
                //todo
                score = 50;
                break;
            case 2: //app
                //todo
                score = 100;
                break;
        }

        System.out.println("送給使用者" + score + "分");
    }
}

複製程式碼

業務呼叫:

package design.pattern.reward;

public class PayNotify {

    public static void main(String[] args) {

        Reward reward = new Reward(2);
        reward.giveScore();
    }
}
複製程式碼

當我們的演算法越來越多,越來越複雜的時候,並且當某個演算法發生變化,將對所有其他計算方式都會產生影響,不能有效的彈性、清晰的擴充,所以這個時候我們的策略模式就上場了。

策略模式UML圖(畫圖工具不工作了)

設計模式第二講--策略模式

策略模式實現

1.首先介面宣告-抽象策略

package design.pattern.reward.score;

public interface InterfaceScore {

    /**
     * 送積分
     */
    public void giveScore();
}
複製程式碼

2.我們實現介面的giveScore方法-實現具體策略演算法

app端積分

package design.pattern.reward.score;

public class AppScore implements InterfaceScore {

    private int score = 100;

    /**
     * 送積分
     */
    public void giveScore() {
        //todo 具體演算法邏輯
        System.out.println("送你積分" + score);
    }
}
複製程式碼

web端積分:

package design.pattern.reward.score;

public class WebScore implements InterfaceScore {

    private int score = 20;

    /**
     * 送積分
     */
    public void giveScore() {
        //todo 具體演算法邏輯
        System.out.println("送你積分" + score);
    }
}
複製程式碼
  1. 不同策略演算法排程類
package design.pattern.reward;

import design.pattern.reward.score.InterfaceScore;

public class Context {

    private InterfaceScore scoreObj;

    public Context(InterfaceScore algorithmObj) {
        this.scoreObj = algorithmObj;
    }

    public void giveScore() {
        this.scoreObj.giveScore();
    }

}
複製程式碼
  1. 客戶端呼叫
Context context1 = new Context(new AppScore());
context1.giveScore();

Context context2 = new Context(new WebScore());
context2.giveScore();
複製程式碼

output:

送你積分100
送你積分20
複製程式碼

好像跟我們剛開始的呼叫方法不一樣,約定好的是傳一個type值來確定計算的方法,現在直接將計算規則方法暴露給了呼叫方

繼續改造 策略模式+簡單工廠

package design.pattern.reward;

import design.pattern.reward.score.AppScore;
import design.pattern.reward.score.InterfaceScore;
import design.pattern.reward.score.WebScore;

public class Context {

    private InterfaceScore scoreObj;

    public Context(int platform) {
        switch (platform) {
            case 0: //web
                this.scoreObj = new WebScore();
                break;
            case 1: //小程式
                //todo
                break;
            case 2: //app
                this.scoreObj = new AppScore();
                break;
        }

    }

    public void giveScore() {
        this.scoreObj.giveScore();
    }
}
複製程式碼

呼叫:

Context context1 = new Context(0);
context1.giveScore();

Context context2 = new Context(2);
context2.giveScore();
複製程式碼

是不是很簡單。。。

總結:

策略模式是一種定義一系列演算法的方法,從概念上來看,所有這些演算法完成的都是相同的工作,只是實現不同,他可以以相同的方式呼叫所有的演算法.減少了演算法與使用演算法之間的耦合.

策略模式是用來封裝演算法的,但在實踐中我們可以用它來封裝幾乎任何型別的規則, 只要在分析過程中需要在不同時間應用不同的業務規則,就可以考慮使用策略模式處理這種變化的可能性。

和上次講到的模版方法模式差異

模版方法模式使用了繼承方式實現演算法,而策略模式使用了組合方式 模版方法模式對於演算法擁有絕對的控制,而策略模式不對演算法控制 模版方法的依賴程度要比策略模式高 。。。。。

更多精彩內容關注呆呆公眾號:

設計模式第二講--策略模式

相關文章