首先,定義接口或抽象父類。例如,定義一個Strategy接口,里面有execute方法。然后不同的策略類實現這個接口,比如ConcreteStrategyA、ConcreteStrategyB等,每個類用@Component注解,可能指定Bean的名字,或者用默認的類名首字母小寫作為Bean名稱。
然后,需要將這些Bean自動注入到一個Map中。Spring支持將同一類型的Bean注入到Map中,其中鍵是Bean的名稱,值是對應的實例。例如,在某個服務類中,使用@Autowired private Map<String, Strategy> strategies; 這樣,Spring會自動將所有的Strategy實現類放入這個Map,鍵是Bean的名稱。
接下來,當需要執行某個策略時,根據傳入的key(即Bean的名稱)從Map中獲取對應的實例,調用其execute方法。例如,在服務類中有一個方法,接收策略名稱作為參數,然后調用strategies.get(name).execute()。
在Spring框架中,使用策略模式并結合依賴注入可以通過以下步驟實現將子類實例存入Map,并通過指定名稱執行對應方法:
1. 定義策略接口或抽象類
public interface PaymentStrategy {void processPayment(double amount);
}
2. 實現具體策略類(子類)
使用@Component
并為每個策略指定唯一的Bean名稱:
@Component("creditCard")
public class CreditCardPayment implements PaymentStrategy {@Overridepublic void processPayment(double amount) {System.out.println("使用信用卡支付:" + amount);}
}@Component("alipay")
public class AlipayPayment implements PaymentStrategy {@Overridepublic void processPayment(double amount) {System.out.println("使用支付寶支付:" + amount);}
}
3. 注入策略Map并執行
@Service
public class PaymentService {private final Map<String, PaymentStrategy> strategies;// 通過構造器注入,Key為Bean名稱,Value為實例@Autowiredpublic PaymentService(Map<String, PaymentStrategy> strategyMap) {this.strategies = strategyMap;}public void executePayment(String method, double amount) {PaymentStrategy strategy = strategies.get(method);if (strategy == null) {throw new IllegalArgumentException("無此支付方式: " + method);}strategy.processPayment(amount);}
}
4. 使用示例
@RestController
public class PaymentController {@Autowiredprivate PaymentService paymentService;@PostMapping("/pay")public String pay(@RequestParam String method, @RequestParam double amount) {paymentService.executePayment(method, amount);return "支付成功";}
}
關鍵點說明
- 自動注入Map:Spring會自動將相同類型(
PaymentStrategy
)的Bean注入到Map中,Key為Bean名稱,Value為實例。 - 策略擴展:新增支付方式只需添加實現類并用
@Component("新名稱")
標記,無需修改其他代碼。 - 異常處理:當傳入不存在的Key時,需處理策略未找到的情況(如拋出異常或返回默認策略)。
自定義Map鍵名(可選)
若需使用非Bean名稱的Key,可通過自定義注解實現:
定義注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface PaymentType {String value();
}
應用注解到策略類:
@Component
@PaymentType("credit")
public class CreditCardPayment implements PaymentStrategy { ... }
手動構建策略Map:
@Service
public class PaymentService {private final Map<String, PaymentStrategy> strategies = new HashMap<>();@Autowiredpublic PaymentService(List<PaymentStrategy> strategyList) {for (PaymentStrategy strategy : strategyList) {PaymentType annotation = strategy.getClass().getAnnotation(PaymentType.class);if (annotation != null) {strategies.put(annotation.value(), strategy);}}}// 其他代碼不變
}
這種方法允許更靈活地定義策略名稱,同時保持代碼的可擴展性。
@sercice(“queryability”)
public class QueryAbilityService implement Strategy{…}
private Map<String, Strategy> strategy;
strategy.get(“key”).ifPresent(handler->handler.onmessage(input));