定义
策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换
应用场景
一个系统有很多个类,他们之间的区别就在于他们的行为不同。
Demo:模拟简单支付场景
package com.ns.strategy;
import java.math.BigDecimal;
/**
* 各种支付方式的顶层抽象接口
*/
public interface IPayService {
void pay(BigDecimal amt);
}
package com.ns.strategy;
import java.math.BigDecimal;
/**
* QQ支付方式
*/
public class QQPay implements IPayService{
@Override
public void pay(BigDecimal amt) {
System.out.println("通过QQ进行支付"+amt+"元");
}
}
package com.ns.strategy;
import java.math.BigDecimal;
/**
* 微信支付
*/
public class WechatPay implements IPayService{
@Override
public void pay(BigDecimal amt) {
System.out.println("通过微信支付"+amt+"元");
}
}
package com.ns.strategy;
import java.math.BigDecimal;
/**
* 通过银行卡进行支付
*/
public class BankPay implements IPayService{
@Override
public void pay(BigDecimal amt) {
System.out.println("通过银行卡支付"+amt+"元");
}
}
package com.ns.strategy;
import java.math.BigDecimal;
/**
* 默认支付方式:现金
*/
public class DefaultPay implements IPayService{
@Override
public void pay(BigDecimal amt) {
System.out.println("使用现金支付"+amt+"元");
}
}
package com.ns.strategy;
/**
* 支付方式枚举类
*/
public enum PayTypeEnum {
PAY_TYPE_QQ("QQ","QQ支付"),
PAY_TYPE_WECHAT("WECHAT","微信支付"),
PAY_TYPE_DEFAULT("DEFAULT","默认支付方式"),
PAY_TYPE_BANK("BANK","银行卡支付");
private String code;
private String name;
PayTypeEnum(String code, String name){
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
}
package com.ns.strategy;
import java.util.HashMap;
import java.util.Map;
/**
* 支付策略类
*/
public class PayStrategy {
private static Map<String,IPayService> PAY_MAP = new HashMap<>();
//静态块,给PAY_MAP赋值
static {
PAY_MAP.put(PayTypeEnum.PAY_TYPE_QQ.getCode(),new QQPay());
PAY_MAP.put(PayTypeEnum.PAY_TYPE_WECHAT.getCode(),new WechatPay());
PAY_MAP.put(PayTypeEnum.PAY_TYPE_BANK.getCode(),new BankPay());
PAY_MAP.put(PayTypeEnum.PAY_TYPE_DEFAULT.getCode(),new DefaultPay());
}
//单例模式的体现
private PayStrategy(){}
/**
* 获取支付类型对应支付方式实例
* @param type
* @return
*/
public static IPayService getInstance(String type){
if(PAY_MAP.containsKey(type)){
return PAY_MAP.get(type);
}else{
throw new RuntimeException("no bean found for type "+type);
}
}
}
package com.ns.strategy;
import java.math.BigDecimal;
/**
* 订单类,简单的订单,只有金额字段
*/
public class Order {
private BigDecimal amt;
public Order(BigDecimal amt){
this.amt = amt;
}
public void pay(String type) {
if(null == type || type.trim().isEmpty()){
type = PayTypeEnum.PAY_TYPE_DEFAULT.getCode();
}
IPayService payService = PayStrategy.getInstance(type);
payService.pay(amt);
}
}
package com.ns.strategy;
import java.math.BigDecimal;
/**
* 测试类
*/
public class TestStrategy {
public static void main(String[] args) {
Order order = new Order(new BigDecimal(100));
order.pay(PayTypeEnum.PAY_TYPE_BANK.getCode());
}
}
策略模式优点
1.符合开闭原则
2.避免过多使用条件语句
3.提高算法的保密性和安全性
缺点
1.客户端必须先知道有多少种策略,并且什么场景调用哪个策略
2.代码中会产生很多的策略类,增加代码维护难度
注:真实业务场景很多都可以使用策略+模板+工厂+单例结合使用来实现
希望大家都可以学以致用