前言
对于很多程序员,平时写代码为了方便,可能一股脑就按面向过程那样一下把业务逻辑编写下来,少有会去额外思考设计模式或者算法。这种情况其实不利于我们的编码维护,在本文,将介绍设计模式中的策略模式,通过本文的介绍将帮助你快速理解和应用。
1、什么是策略模式?
策略模式是一种行为型设计模式,它通过暴露一个统一的接口,通过该接口在不同情况下根据类型执行不同的逻辑的行为。策略模式解决了在有多种算法相似的情况下,使用“if…else”所带来的复杂和难以维护的问题。
2、策略模式的结构
策略模式包括以下几个角色:
**上下文(Context):**持有一个策略对象的引用,并在需要时调用策略对象的方法。上下文可以根据具体情况选择不同的策略。
**策略(Strategy):**定义了一个公共接口,用于封装不同的算法。这个接口通常只有一个方法,即执行算法的方法。
具体策略(ConcreteStrategy):实现了策略接口,提供具体的算法实现。每个具体策略类都代表了一种特定的算法。
-策略模式的关键在于上下文持有一个策略对象的引用,并且通过调用策略对象的方法来执行具体的算法。这种方式使得上下文变得非常灵活,可以根据不同的需求在运行时切换算法。
3、策略模式的应用例子
策略模式适用于以下情况:
- 当需要在运行时动态地选择算法实现时,可以使用策略模式。
- 当一个类有多个行为变种,并且这些行为可以灵活地切换时,策略模式可以提供一种优雅的解决方案。
例:比如我们常见的支付行为,当你买了一个车票,这时候发起支付可以选择微信、支付宝、银行卡等,此时我们编写一个支付接口,大多数人可能会写成如下代码:
@GetMapping(value = "/pay", produces = MediaType.APPLICATION_JSON_VALUE)
public String pay(String payType) {
if(payType=="ALI_PAY"){
System.out.println("执行支付宝的支付逻辑");
}else if(payType=="WEIXIN_PAY"){
System.out.println("执行微信的支付逻辑");
}else{
System.out.println(".......等等");
}
return "success";
}
当你需要加上其他类型的支付时,就不断在后面加else if,其实这违背了面向对象设计的六大原则中的单一职责和开闭原则(对扩展开放、对修改关闭)。因此我们可以用策略模式改造一下
创建一个支付处理逻辑接口
//支付处理器接口
public interface PayHandler {
void pay();
}
创建不同支付的支付实现类
这里创建两个实现类,分别为支付宝和微信的支付实现类
@Component("AliPayHandler")
public class AliPayHandler implements PayHandler{
@Override
public void pay() {
System.out.println("支付宝支付逻辑");
}
}
@Component("WeixinPayHandler ")
public class WeixinPayHandler implements PayHandler{
@Override
public void pay() {
System.out.println("微信支付逻辑");
}
}
创建一个枚举类
映射不同的支付类型和对应的处理器
public enum PayHandlerEnum {
ALI_PAY("ALI_PAY", "AliPayHandler"),
WEIXIN_PAY("WEIXIN_PAY", "WeixinPayHandler");
final String code;
final String name;
public String getCode() {
return code;
}
public String getName() {
return name;
}
PayHandlerEnum(String code, String name) {
this.code = code;
this.name = name;
}
public static String getNameByCode(String code) {
PayHandlerEnum[] payHandlerEnums = values();
for (PayHandlerEnum payHandlerEnum : payHandlerEnums) {
if (payHandlerEnum.getCode().equals(code)) {
return payHandlerEnum.getName();
}
}
return null;
}
}
controller支付接口
@GetMapping(value = "/pay")
public String pay(@RequestParam String payType) {
PayHandler handler = (PayHandler) applicationContext.getBean(Objects.requireNonNull(PayHandlerEnum.getNameByCode(payType)));
handler.pay();
return "success";
}