初識設計模式

2022-10-19 12:00:56

簡介

策略設計模式(Strategy Design Pattern)實際上起到一個解耦的作用,解耦了策略的定義、建立、使用三部分。

其概念是,定義一系列演演算法類,將每一個演演算法封裝起來,並讓它們可以互相替換。

從程式碼的層面上理解就是,將程式導向程式設計中的分支(如 if-else 或 switch 分支)程式碼,轉換成物件導向的演演算法類,通過構建這些類的關係以實現不同分支的選擇,實現執行時選擇策略。

具體實現

在這裡,使用一個加、減、乘的案例來展示策略模式的應用。

首先,對加、減、乘運算抽象出一個公共的方法,定義一個 Strategy 策略介面,其程式碼範例如下:

public interface Strategy {
    // 加、減、乘、除都是對兩個數進行處理
    int doOperation(int num1, int num2);
}

對於加法,實現 Strategy 策略介面,定義一個 OperationAdd 策略類,其程式碼範例如下:

public class OperationAdd implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

對於減法,實現 Strategy 策略介面,定義一個 OperationSubtract 策略類,其程式碼範例如下:

public class OperationSubtract implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}

對於乘法,實現 Strategy 策略介面,定義一個 OperationMultiply 策略類,其程式碼範例如下:

public class OperationMultiply implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 * num2;
    }
}

通常,會定義一個 Context 類用於彙總策略類,以方便使用者端使用,其程式碼範例如下:

public class Context {
    private final Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int num1, int num2) {
        return strategy.doOperation(num1, num2);
    }
}

對於使用者端而言,需要理解 Context 類如何使用,以及知道所有的策略類,通過注入不同的 Strategy 物件以達到選擇不同策略的效果。

如下是使用者端使用策略模式的程式碼範例:

public class StrategyDemo {
    public static void main(String[] args) {
        Context context = new Context(new OperationAdd());
        // 10 + 5 = 15
        System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

        context = new Context(new OperationSubtract());
        // 10 - 5 = 5
        System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

        context = new Context(new OperationMultiply());
        // 10 * 5 = 50
        System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
    }
}

總結

優點

策略模式的主要優點如下:

  • 使用策略模式可以避免使用多重條件語句,如 if-else 或 switch 語句
  • 策略模式提供了管理相關演演算法族的辦法,如恰當地使用繼承把演演算法族的公共程式碼轉移到父類別中
  • 策略模式提供了相同行為的不同實現,使用者端可以根據不同的需求使用不同的策略
  • 可以在不更改原始碼的模式下,靈活增加新的演演算法,符合開閉原則
  • 策略模式把演演算法的使用放到環境類中,把實現放到具體策略類中,把定義放到使用者端中,實現了三者的解耦

缺點

策略模式的主要缺點如下:

  • 使用者端必須知道所有的策略類,並自行決定使用哪一個策略類
  • 策略模式造成很多策略類,增加了維護難度

適用場景

策略模式的適用場景如下:

  • 一個系統需要動態地在幾種演演算法中選擇一種時,可將每個演演算法封裝到策略類中
  • 對於多重條件語句,使用策略模式將這些行為轉移到相應的具體策略類中,以替代這些條件語句
  • 系統要求使用演演算法的使用者端不應該知道其操作的資料時,可以使用策略模式來封裝演演算法及其資料結構

原始碼

在 JDK 中,Comparator 介面就是一個策略模式的應用。

實際使用時,Comparator 就是策略介面,使用匿名內部類來實現具體策略類。如下是使用的範例程式碼:

import java.util.Arrays;
import java.util.Comparator;

public class ComparatorDemo {
    public static void main(String[] args) {
        String[] names = {"張三", "李四", "小明"};
        Comparator<String> comparator = new Comparator<>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        };
        Arrays.sort(names, comparator);
        // [小明, 張三, 李四]
        System.out.println(Arrays.toString(names));
    }
}