JAVA中六種策略模式的實現(xiàn)方式(附代碼示例和適用場景)
前言
在 Java 中,策略模式的核心是定義算法族、封裝算法、動態(tài)切換,其實現(xiàn)方式主要圍繞 “策略的定義、創(chuàng)建、選擇” 展開,根據(jù)場景復(fù)雜度和技術(shù)選型,常見有以下 6 種實現(xiàn)方式,附代碼示例和適用場景:
一、基礎(chǔ)實現(xiàn):接口 + 實現(xiàn)類(經(jīng)典方式)
最標準的實現(xiàn),通過接口定義策略契約,多個實現(xiàn)類封裝不同算法,客戶端通過注入或選擇不同實現(xiàn)類切換策略。
代碼示例
// 1. 策略接口(定義契約)
public interface PaymentStrategy {
// 策略核心方法:支付
boolean pay(double amount);
// 獲取策略名稱
String getStrategyName();
}
// 2. 具體策略1:支付寶支付
public class AlipayStrategy implements PaymentStrategy {
@Override
public boolean pay(double amount) {
System.out.println("使用支付寶支付:" + amount + "元");
return true; // 模擬支付成功
}
@Override
public String getStrategyName() {
return "alipay";
}
}
// 3. 具體策略2:微信支付
public class WechatPayStrategy implements PaymentStrategy {
@Override
public boolean pay(double amount) {
System.out.println("使用微信支付:" + amount + "元");
return true;
}
@Override
public String getStrategyName() {
return "wechat";
}
}
// 4. 策略上下文(封裝策略,對外提供統(tǒng)一接口)
public class PaymentContext {
private PaymentStrategy strategy;
// 構(gòu)造器注入策略
public PaymentContext(PaymentStrategy strategy) {
this.strategy = strategy;
}
// 動態(tài)切換策略
public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
// 客戶端調(diào)用入口
public boolean executePayment(double amount) {
return strategy.pay(amount);
}
}
// 5. 客戶端使用
public class Client {
public static void main(String[] args) {
// 選擇支付寶策略
PaymentContext context = new PaymentContext(new AlipayStrategy());
context.executePayment(100);
// 動態(tài)切換為微信策略
context.setStrategy(new WechatPayStrategy());
context.executePayment(200);
}
}
適用場景
- 策略數(shù)量固定、變化不頻繁(如支付方式、排序算法)。
- 需明確暴露所有策略,允許客戶端直接選擇。
二、枚舉實現(xiàn)(簡化策略管理)
用枚舉封裝所有策略,利用枚舉的 “單例特性” 和 “天然分組” 優(yōu)勢,減少類冗余,簡化策略選擇。
代碼示例
// 1. 枚舉策略(實現(xiàn)策略邏輯)
public enum PaymentStrategyEnum {
// 支付寶策略
ALIPAY {
@Override
public boolean pay(double amount) {
System.out.println("枚舉-支付寶支付:" + amount + "元");
return true;
}
},
// 微信支付策略
WECHAT {
@Override
public boolean pay(double amount) {
System.out.println("枚舉-微信支付:" + amount + "元");
return true;
}
};
// 策略核心方法(枚舉抽象方法)
public abstract boolean pay(double amount);
}
// 2. 客戶端使用(直接通過枚舉選擇策略)
public class Client {
public static void main(String[] args) {
// 根據(jù)枚舉值選擇策略
PaymentStrategyEnum.ALIPAY.pay(100);
PaymentStrategyEnum.WECHAT.pay(200);
// 支持動態(tài)傳入策略(如從配置文件讀取)
String strategyName = "ALIPAY"; // 可來自配置
PaymentStrategyEnum strategy = Enum.valueOf(PaymentStrategyEnum.class, strategyName);
strategy.pay(300);
}
}
適用場景
- 策略數(shù)量少、邏輯簡單(如狀態(tài)判斷、固定規(guī)則)。
- 無需動態(tài)擴展策略(枚舉不可動態(tài)新增)。
三、工廠模式 + 策略模式(解耦策略創(chuàng)建)
通過工廠類封裝策略的創(chuàng)建邏輯,客戶端無需關(guān)注策略的實例化細節(jié),只需傳入標識即可獲取對應(yīng)策略,適合策略較多的場景。
代碼示例
// 1. 策略接口(同基礎(chǔ)實現(xiàn))
public interface PaymentStrategy {
boolean pay(double amount);
String getStrategyCode();
}
// 2. 具體策略(同基礎(chǔ)實現(xiàn):AlipayStrategy、WechatPayStrategy)
// 3. 策略工廠(封裝策略創(chuàng)建)
public class PaymentStrategyFactory {
// 緩存策略實例(單例)
private static final Map<String, PaymentStrategy> STRATEGY_MAP = new HashMap<>();
// 靜態(tài)初始化:注冊所有策略
static {
STRATEGY_MAP.put("alipay", new AlipayStrategy());
STRATEGY_MAP.put("wechat", new WechatPayStrategy());
}
// 禁止外部實例化
private PaymentStrategyFactory() {}
// 根據(jù)標識獲取策略
public static PaymentStrategy getStrategy(String strategyCode) {
PaymentStrategy strategy = STRATEGY_MAP.get(strategyCode);
if (strategy == null) {
throw new IllegalArgumentException("不支持的支付方式:" + strategyCode);
}
return strategy;
}
// 擴展:動態(tài)注冊新策略(支持熱更新)
public static void registerStrategy(String code, PaymentStrategy strategy) {
STRATEGY_MAP.put(code, strategy);
}
}
// 4. 客戶端使用
public class Client {
public static void main(String[] args) {
// 從工廠獲取策略(無需手動new)
PaymentStrategy alipay = PaymentStrategyFactory.getStrategy("alipay");
alipay.pay(100);
PaymentStrategy wechat = PaymentStrategyFactory.getStrategy("wechat");
wechat.pay(200);
// 動態(tài)注冊新策略(如新增銀聯(lián)支付)
PaymentStrategyFactory.registerStrategy("unionpay", new UnionPayStrategy());
PaymentStrategyFactory.getStrategy("unionpay").pay(300);
}
}
// 新增策略:銀聯(lián)支付(無需修改工廠核心邏輯)
class UnionPayStrategy implements PaymentStrategy {
@Override
public boolean pay(double amount) {
System.out.println("使用銀聯(lián)支付:" + amount + "元");
return true;
}
@Override
public String getStrategyCode() {
return "unionpay";
}
}
適用場景
- 策略數(shù)量多(如 10+),需要統(tǒng)一管理創(chuàng)建邏輯。
- 客戶端只需通過標識(如字符串、枚舉)選擇策略,無需關(guān)注實現(xiàn)。
四、注解 + 反射(動態(tài)掃描策略)
通過自定義注解標記策略類,程序啟動時掃描所有帶注解的策略并注冊到工廠,支持 “無侵入式擴展”(新增策略無需修改工廠代碼)。
代碼示例
// 1. 自定義策略注解(標記策略標識)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PaymentStrategyAnnotation {
String code(); // 策略唯一標識
}
// 2. 策略接口(同基礎(chǔ)實現(xiàn))
public interface PaymentStrategy {
boolean pay(double amount);
}
// 3. 具體策略(用注解標記)
@PaymentStrategyAnnotation(code = "alipay")
public class AlipayStrategy implements PaymentStrategy {
@Override
public boolean pay(double amount) {
System.out.println("注解-支付寶支付:" + amount + "元");
return true;
}
}
@PaymentStrategyAnnotation(code = "wechat")
public class WechatPayStrategy implements PaymentStrategy {
@Override
public boolean pay(double amount) {
System.out.println("注解-微信支付:" + amount + "元");
return true;
}
}
// 4. 策略工廠(反射掃描注解策略)
public class AnnotationStrategyFactory {
private static final Map<String, PaymentStrategy> STRATEGY_MAP = new HashMap<>();
// 初始化:掃描指定包下的所有策略
static {
try {
// 掃描com.example.strategy包下的所有類
Reflections reflections = new Reflections("com.example.strategy");
// 獲取所有帶@PaymentStrategyAnnotation注解的類
Set<Class<?>> strategyClasses = reflections.getTypesAnnotatedWith(PaymentStrategyAnnotation.class);
// 實例化并注冊策略
for (Class<?> clazz : strategyClasses) {
PaymentStrategyAnnotation annotation = clazz.getAnnotation(PaymentStrategyAnnotation.class);
String code = annotation.code();
PaymentStrategy strategy = (PaymentStrategy) clazz.newInstance();
STRATEGY_MAP.put(code, strategy);
}
} catch (Exception e) {
throw new RuntimeException("策略初始化失敗", e);
}
}
// 獲取策略
public static PaymentStrategy getStrategy(String code) {
return STRATEGY_MAP.getOrDefault(code, () -> {
System.out.println("默認策略:支付失敗");
return false;
});
}
}
// 5. 客戶端使用(依賴Reflections庫,需導(dǎo)入依賴)
public class Client {
public static void main(String[] args) {
AnnotationStrategyFactory.getStrategy("alipay").pay(100);
AnnotationStrategyFactory.getStrategy("wechat").pay(200);
}
}
依賴說明
需導(dǎo)入反射掃描庫(Maven):
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
</dependency>
適用場景
- 大型項目,策略頻繁新增(如插件化架構(gòu))。
- 追求 “開閉原則”,新增策略無需修改現(xiàn)有代碼。
五、Lambda 表達式(簡化無狀態(tài)策略)
對于無狀態(tài)、邏輯簡單的策略,可直接用 Lambda 表達式實現(xiàn)策略接口,無需創(chuàng)建單獨的實現(xiàn)類,簡化代碼。
代碼示例
// 1. 函數(shù)式策略接口(僅含一個抽象方法)
@FunctionalInterface
public interface PaymentStrategy {
boolean pay(double amount);
}
// 2. 策略上下文(同基礎(chǔ)實現(xiàn))
public class PaymentContext {
private PaymentStrategy strategy;
public PaymentContext(PaymentStrategy strategy) {
this.strategy = strategy;
}
public boolean execute(double amount) {
return strategy.pay(amount);
}
}
// 3. 客戶端使用(Lambda直接實現(xiàn)策略)
public class Client {
public static void main(String[] args) {
// Lambda實現(xiàn)支付寶策略
PaymentContext alipayContext = new PaymentContext(amount -> {
System.out.println("Lambda-支付寶支付:" + amount + "元");
return true;
});
alipayContext.execute(100);
// Lambda實現(xiàn)微信策略
PaymentContext wechatContext = new PaymentContext(amount -> {
System.out.println("Lambda-微信支付:" + amount + "元");
return true;
});
wechatContext.execute(200);
// 甚至可以直接傳遞Lambda,無需上下文
PaymentStrategy unionPay = amount -> {
System.out.println("Lambda-銀聯(lián)支付:" + amount + "元");
return true;
};
unionPay.pay(300);
}
}
適用場景
- 策略邏輯簡單(1-3 行代碼)、無狀態(tài)(無需成員變量)。
- 臨時策略(僅使用一次),無需復(fù)用。
六、Spring 容器整合(依賴注入 + 自動裝配)
在 Spring 項目中,利用 Spring 的 IOC 容器管理策略實例,通過@Autowired自動注入所有策略,結(jié)合Map或List實現(xiàn)策略選擇,無需手動創(chuàng)建工廠。
代碼示例
// 1. 策略接口(同基礎(chǔ)實現(xiàn))
public interface PaymentStrategy {
boolean pay(double amount);
String getStrategyCode();
}
// 2. 具體策略(Spring組件)
@Component // 交給Spring管理
public class AlipayStrategy implements PaymentStrategy {
@Override
public boolean pay(double amount) {
System.out.println("Spring-支付寶支付:" + amount + "元");
return true;
}
@Override
public String getStrategyCode() {
return "alipay";
}
}
@Component
public class WechatPayStrategy implements PaymentStrategy {
@Override
public boolean pay(double amount) {
System.out.println("Spring-微信支付:" + amount + "元");
return true;
}
@Override
public String getStrategyCode() {
return "wechat";
}
}
// 3. 策略服務(wù)(Spring組件,自動注入所有策略)
@Service
public class PaymentService {
// Spring會自動將所有PaymentStrategy實現(xiàn)類注入到Map中:key=beanName,value=策略實例
@Autowired
private Map<String, PaymentStrategy> strategyMap;
// 或按策略code映射(自定義key)
private Map<String, PaymentStrategy> codeToStrategyMap;
// 初始化:將策略按code分組
@PostConstruct
public void init() {
codeToStrategyMap = strategyMap.values().stream()
.collect(Collectors.toMap(PaymentStrategy::getStrategyCode, s -> s));
}
// 執(zhí)行策略
public boolean executePayment(String strategyCode, double amount) {
PaymentStrategy strategy = codeToStrategyMap.get(strategyCode);
if (strategy == null) {
throw new IllegalArgumentException("不支持的支付方式");
}
return strategy.pay(amount);
}
}
// 4. 客戶端使用(Spring環(huán)境)
@SpringBootApplication
public class StrategyApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(StrategyApplication.class, args);
PaymentService paymentService = context.getBean(PaymentService.class);
paymentService.executePayment("alipay", 100);
paymentService.executePayment("wechat", 200);
}
}
適用場景
- Spring Boot/Spring MVC 項目(充分利用 Spring 的 IOC 特性)。
- 策略需要依賴其他 Spring 組件(如
@Autowired數(shù)據(jù)源、緩存等)。
六種實現(xiàn)方式對比
| 實現(xiàn)方式 | 優(yōu)點 | 缺點 | 適用場景 |
|---|---|---|---|
| 接口 + 實現(xiàn)類(經(jīng)典) | 結(jié)構(gòu)清晰、易理解 | 策略多時有類爆炸問題 | 策略少、變化不頻繁 |
| 枚舉實現(xiàn) | 代碼簡潔、無類冗余 | 策略邏輯復(fù)雜時不適用,不可動態(tài)擴展 | 策略少、邏輯簡單 |
| 工廠 + 策略 | 解耦創(chuàng)建邏輯、支持動態(tài)擴展 | 新增策略需修改工廠注冊代碼 | 策略較多、需要統(tǒng)一管理 |
| 注解 + 反射 | 無侵入擴展、支持插件化 | 依賴反射庫、初始化開銷略大 | 大型項目、策略頻繁新增 |
| Lambda 表達式 | 代碼極簡、無需創(chuàng)建類 | 無狀態(tài)、邏輯簡單場景受限 | 臨時策略、簡單邏輯 |
| Spring 整合 | 自動注入、支持依賴管理 | 依賴 Spring 環(huán)境 | Spring 項目、策略需依賴其他組件 |
核心設(shè)計原則
無論哪種實現(xiàn)方式,都需遵循:
- 開閉原則:新增策略無需修改現(xiàn)有代碼(枚舉方式除外)。
- 單一職責:每個策略只負責一種算法,上下文只負責協(xié)調(diào)策略。
- 里氏替換:任何策略都可替換為其他實現(xiàn),不影響客戶端使用。
總結(jié)
到此這篇關(guān)于JAVA中六種策略模式實現(xiàn)方式的文章就介紹到這了,更多相關(guān)JAVA策略模式實現(xiàn)方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java面向?qū)ο笾甪inal關(guān)鍵字詳細解讀
這篇文章主要介紹了Java面向?qū)ο笾甪inal關(guān)鍵字詳細解讀,final修飾的屬性又叫常量,一般用 XX_XX_XX來命名,final修飾的屬性在定義時必須賦初始值,并且以后不能再修改,需要的朋友可以參考下2024-01-01
SpringBoot3整合 Elasticsearch 8.x 使用Repository構(gòu)
我們構(gòu)建了一個完整的 Spring Boot 3 和 Elasticsearch 8.x 的增刪改查示例應(yīng)用,使用 Spring Data Elasticsearch Repository,我們能夠快速實現(xiàn)對 Elasticsearch 的基本 CRUD 操作,簡化了開發(fā)流程,希望這個示例能夠幫助你理解如何在項目中有效使用 Elasticsearch!2024-11-11
Spring中的@ExceptionHandler注解統(tǒng)一異常處理詳解
這篇文章主要介紹了Spring中的@ExceptionHandler注解統(tǒng)一異常處理詳解,當我們使用這個@ExceptionHandler注解時,定義一個異常的處理方法,加上@ExceptionHandler注解,這個方法就會處理類中其他方法拋出的異常,需要的朋友可以參考下2024-01-01
詳解springboot接口如何優(yōu)雅的接收時間類型參數(shù)
這篇文章主要為大家詳細介紹了springboot的接口如何優(yōu)雅的接收時間類型參數(shù),文中為大家整理了三種常見的方法,希望對大家有一定的幫助2023-09-09

