设计模式-策略模式

策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不同的对象管理。 策略模式通常把一个系列的算法封装到一系列的策略类里面,作为一个抽象策略类的子类。 用一句话来说,就是“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。

策略模式包含如下角色:

  • Context: 环境类
  • Strategy: 抽象策略类
  • ConcreteStrategy: 具体策略类

现在来根据角色实现一个支付策略:

首先定义一个支付接口:PayStrategy

1
2
3
public interface PayStrategy {
String doPay(String type, Map<String, Object> param);
}

定义具体的实现类之微信支付:WeChatPay

1
2
3
4
5
6
7
@Component
public class WeChatPay implements PayStrategy {
@Override
public String doPay(String type, Map<String, Object> param) {
return "微信支付";
}
}

定义具体的实现类之支付宝支付:ALiPay

1
2
3
4
5
6
7
8
@Component
public class ALiPay implements PayStrategy {

@Override
public String doPay(String type, Map<String, Object> param) {
return "支付宝支付";
}
}

定义具体的实现类之银联支付:UnionPay

1
2
3
4
5
6
7
@Component
public class UnionPay implements PayStrategy {
@Override
public String doPay(String type, Map<String, Object> param) {
return "银联支付";
}
}

定义一个上下文类,提供不同算法的组合和选择:PayContext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Component
public class PayContext {
private Map<PayType, PayStrategy> payStrategyMap = new HashMap<> ( );
@Autowired
WeChatPay weChatPay;
@Autowired
ALiPay aLiPay;
@Autowired
UnionPay unionPay;

@PostConstruct
void initStrategyMap() {
this.payStrategyMap.put ( PayType.WECHATPAY, weChatPay);
this.payStrategyMap.put ( PayType.ALIPAY, aLiPay);
this.payStrategyMap.put ( PayType.UNIONPAY, unionPay);
}

public String doCmd(String type, Map<String, Object> param) {
return this.payStrategyMap.get ( PayType.getPayType ( type ) ).doPay ( type, param );
}
}

其中PayType是类型枚举:PayType

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public enum PayType {
WECHATPAY("WECHAT", "微信支付"),
ALIPAY("ALI", "支付宝支付"),
UNIONPAY("UNION", "银联支付");

private String type;
private String desc;

PayType(String type, String desc) {
this.type = type;
this.desc = desc;
}

public static PayType getPayType(String type) {
for (PayType payType: PayType.values ()
) {
if (payType.type.equalsIgnoreCase ( type )) {
return payType;
}
}
return null;
}
}

最后定义一个controller类来使用我们的支付策略:PayUsage

1
2
3
4
5
6
7
8
9
10
11
@RestController
public class PayUsage {
@Autowired
private PayContext payContext;

@RequestMapping("/pay")
public String usePay(@RequestParam String type) {
//测试参数null
return payContext.doCmd ( type, null);
}
}

传不同的类型参数调用接口,即使用不同的策略:

curl localhost/pay?type=wechat 返回微信支付

curl localhost/pay?type=ali 返回支付宝支付

curl localhost/pay?type=union 返回银联支付

-------------本文结束感谢您的阅读-------------
Good for you!