GoF设计模式(十三) - 策略模式

本文介绍了如何利用策略模式来实现支付方式的多样化,详细阐述了策略模式的组成,包括上下文类、抽象策略类和具体策略类,并通过支付类型的实例展示了其实现。文章还讨论了简单工厂模式作为优化手段,但指出其仍有改进空间。最后,提出了一种使用Spring的ApplicationContextAware接口来创建支付策略工厂的方法,使得在增加新支付策略时无需修改上下文类,降低了代码的耦合度。
摘要由CSDN通过智能技术生成

前言

策略模式属于行为型模式,是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。

组成

上下文类(PayContext): 维护一个对PayStrategy对象的引用。
抽象策略类(PayStrategy): 定义所有支持的算法的公共接口或抽象类
具体策略类(AliPayStrategy、JdPayStrategy、WechatPayStrategy): 封装了具体的算法或行为,继承于PayStrategy

 

场景以支付方式为例

1. 支付类型枚举

public enum PayEnum {
    JD,
    ALIPAY,
    WECHAT
}

2. 策略抽象类

public abstract class PayStrategy {

    public abstract PayEnum payType();

    public abstract void pay();

}

3. 具体策略实现类

@Component
public class AliPayStrategy extends PayStrategy{

    @Override
    public PayEnum payType() {
        return PayEnum.ALIPAY;
    }

    @Override
    public void pay() {
        System.out.println("使用支付宝支付");
    }
}

 

@Component
public class JdPayStrategy extends PayStrategy{

    @Override
    public PayEnum payType() {
        return PayEnum.JD;
    }

    @Override
    public void pay() {
        System.out.println("使用京东支付");
    }
}
@Component
public class WechatPayStrategy extends PayStrategy{

    @Override
    public PayEnum payType() {
        return PayEnum.WECHAT;
    }

    @Override
    public void pay() {
        System.out.println("使用微信支付");
    }
}

3. 策略上下文

public class PayContext{

    private PayStrategy payStrategy;

    public PayContext(PayStrategy payStrategy){
       this.payStrategy = payStrategy;
    }

    public void  pay(){
        payStrategy.pay();
    }
}

4. 单元测试

@SpringBootTest
class StrategyDemoApplicationTests {

  
    @Test
    void contextLoads() {
        PayContext payStrategy =new PayContext(new AliPayStrategy());
        payStrategy.pay();
    }

}

5. 运行结果

 

通过实例化不同的策略类会使用不同的支付方式 ,但个人不太推荐使用这种方式(需要在客户端调用通过类型if else 来实例化对应的策略类)

优化:比如我只需要传入一个参数即可,大话设计模式一书中添加了简单工厂模式把if else 或 switch的判定写在了 context上下文中,将业务判定进行了隔离,但还是不太完美,如果新增一个策略类后  还需更改context上下文的switch条件。

如有对简单工厂模式不太了解的可以阅读 https://blog.csdn.net/javanbme/article/details/114922029 。

如何更好的实现?  话不多说直接上示例 。

 

1. 新增支付策略工厂

@Component
public class PayStrategyFactory implements ApplicationContextAware {

    private Map<PayEnum,PayContext> payStrategyMap = new HashMap<>();


    public PayContext getPayStrategy(PayEnum payEnum){
        if (!payStrategyMap.containsKey(payEnum)) {
            throw new IllegalArgumentException("PayContext not exist");
        }
        return payStrategyMap.get(payEnum);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, PayStrategy> beansOfType = applicationContext.getBeansOfType(PayStrategy.class);
        beansOfType.forEach((k, payStrategy) -> {
            payStrategyMap.put(payStrategy.payType(),new PayContext(payStrategy));
        });
    }


}

2. 修改单元测试方法

@SpringBootTest
class StrategyDemoApplicationTests {

    @Autowired
    private PayStrategyFactory payStrategyFactory;

	@Test
	void contextLoads() {
        PayContext payStrategy = payStrategyFactory.getPayStrategy(PayEnum.ALIPAY);
        payStrategy.pay();
    }

}

运行结果和上述一致,而该方式只需指定不同的枚举类型即可, 当添加新的策略类时,无需更改工厂类和上下文! 即核心是使用了Spring的ApplicationContextAware类

不太了解的可以阅读  https://blog.csdn.net/javanbme/article/details/116096885 

源码: https://download.csdn.net/download/javanbme/18274617

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

让程序飞

您的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值