策 略 模 式「指 鼠 為 鴨」

2023-06-11 15:00:11

前言

大家好,我是 god23bin,今天我們來介紹下設計模式中的一個重要的設計模式——策略模式

當涉及到某個行為或演演算法有多個變體時,策略模式是一種常見的設計模式。它允許在執行時選擇使用不同的策略,而無需修改現有程式碼。

現在就使用設計模式中經常出現的鴨子模型來介紹吧!

鴨子模型

鴨子模型也是很好理解的,走路像鴨子,會像鴨子一樣游泳,還會叫出類似嘎嘎嘎的聲音的東西,就是鴨子模型,至於它是不是鴨子,這不重要!

策略模式

定義一系列的演演算法,把它們一個個封裝起來,並且使它們可相互替換。

主要解決在有多種演演算法相似的情況下,使用 if...else 所帶來的複雜和難以維護的問題。

在大學食堂中,有許多的菜品,那麼我們設計一個食物 Food 介面來表示各種菜品,該介面需要具有一個能夠展示各種食物是什麼的能力,就設計成一個 show 方法吧。

public interface Food {
    void show();
}

每種食物菜品都能夠展示,那麼我們定義一個鴨脖策略類 DuckNeckStrategy,作為一個食物菜品的策略。這個類實現 Food 介面,重寫了 show 方法,能夠展示這是一道正兒八經的鴨脖。

public class DuckNeckStrategy implements Food {
    @Override
    public void show() {
        System.out.println("嘎嘎嘎,我是正兒八經的鴨脖。");
    }
}

接著,我們寫一個食物策略類,該策略類也實現 Food 介面,並將食物 Food 介面作為該類的屬性進行宣告,這種稱為組合。同時寫一個帶 Food 介面引數的構造方法。

public class FoodStrategy implements Food {
    private Food food;

    public FoodStrategy(Food food) {
        this.food = food;
    }

    @Override
    public void show() {
        food.show();
    }
}

現在,我們用餐的同學出場了,寫一個 Student 類,定義一個吃正兒八經鴨脖的方法。

public class Student {

    // 吃正兒八經的鴨脖
    public void eatDuckNeck() {
        Food duckNeck = new FoodStrategy(new DuckNeckStrategy());
        System.out.println("開吃!");
        duckNeck.show();
    }

}

現在咱們執行下程式:

public class Main {
    public static void main(String[] args) {
        Student student = new Student();
        student.eatDuckNeck();
    }
}

輸出:

開吃!
嘎嘎嘎,我是正兒八經的鴨脖。

現在我們定義一個老鼠頭策略類 MouseHeadStrategy,作為一道菜品策略,自然也是需要實現 Food 介面,重寫了 show 方法,能夠實現展示鼠頭鴨脖這道菜品。

public class MouseHeadStrategy implements Food {
    @Override
    public void show() {
        System.out.println("吱吱吱,我是長得像鼠頭的鴨脖。");
    }
}

接著,給咱們的同學加餐,多定義一個無奈吃鴨脖的方法,將一個老鼠頭策略作為加餐的引數傳遞到方法中。

public class Student {

    // 吃正兒八經的鴨脖
    public void eatDuckNeck() {
        Food duckNeck = new FoodStrategy(new DuckNeck());
        System.out.println("開吃!");
        duckNeck.show();
    }
	
    // 吱吱吱,吃鴨脖
    public void eatDuckNeck(MouseHeadStrategy mouseHeadStrategy) {
        Food duckNeck = new FoodStrategy(mouseHeadStrategy);
        System.out.println("開吃!");
        duckNeck.show();
    }

}

現在,給 eatDuckNeck 方法傳入一個老鼠頭引數,咱們繼續執行下程式。

public class Main {
    public static void main(String[] args) {
        Student student = new Student();
        // 指鼠為鴨
        student.eatDuckNeck(new MouseHeadStrategy());
    }
}

輸出:

開吃!
吱吱吱,我是長得像鼠頭的鴨脖。

很明顯,程式依舊能夠執行,即使將鼠頭傳入,也能成為鴨脖。這就是策略模式給我們帶來的好處,它允許我們在程式執行時去選擇不同的演演算法或策略來實現某種功能,而無需改變已有的程式碼結構。提高了咱們程式碼的靈活性。

在這個例子中,策略模式可以在執行時通過策略來決定說你吃的是什麼,想怎樣就怎樣,想讓你是鴨脖就是鴨脖,即使你是老鼠頭。

總結

策略模式的寫法:

  1. 定義共同的介面或抽象類來宣告策略類都要實現的方法,就比如這裡的 show 方法。
  2. 定義具體的策略類,比如這裡的 DuckNeckStrategyMouseHeadStrategy,實現介面中的方法,每個具體策略類提供不同的演演算法或行為實現。
  3. 定義使用者端類,比如這裡的 FoodStrategy,持有一個之前定義介面或抽象類的參照,這裡也就是所謂的組合,同時實現介面,實現一個構造方法,用來使用不同的策略來執行重寫的介面方法。
  4. 在程式碼中使用這個使用者端類,傳入不同的策略到構造方法中來實現不同的效果。

本文靈感來源:https://www.bilibili.com/video/BV1jm4y1q76g

最後的最後

希望各位螢幕前的靚仔靚女們給個三連!你輕輕地點了個贊,那將在我的心裡世界增添一顆明亮而耀眼的星!

咱們下期再見!