设计模式太难学?java设计模式之策略模式

导读:本篇文章讲解 设计模式太难学?java设计模式之策略模式,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com


前言

策略模式属于行为型的设计模式。该模式通过定义一系列策略。当需要使用某一种策略时。我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能,如支付策略有微信支付、支付宝支付。登陆策略有第三方微信登陆、QQ登陆、手机号登陆等等。


一、策略模式介绍

策略模式在结构上分为:

  • 抽象策略类,一般是抽象方法或者接口
  • 具体策略实现类,实现或继承抽象策略类
  • 环境类,持有抽象策略的引用,不同环境操作不同策略
  • 客户端

结构图示(来源网络):
图片来自于网络

二、策略模式使用

我们以一个接入第三方支付的需求来介绍如何使用设计模式。需求是现阶段需支持微信支付和支付宝支付,后期可能增加银联支付、数字人名币支付等渠道。

不使用设计模式的情况下会如何实现这种场景呢?
封装一个支付服务类,分别编写微信支付方法、支付宝支付方法。支付调用时,根据条件语句if或者switch判断调用哪种支付方式。

这种方式扩展性很差,当后期需要新增支付渠道时,就得修改支付服务类,新增一个if语句来走新渠道。当支付方式越来越多时,支付处理代码也会越来越臃肿,越来越多的if语句。

在使用策略模式的情况下如何实现场景

根据策略模式的角色先定义好支付方式的策略抽象类以及具体策略实现类

package com.example.study.strategy;

import java.util.Map;
//支付策略抽象类
public interface PayStrategy {
    
    void pay(Map<String,Object> paramsMap);
}


package com.example.study.strategy;

import java.util.Map;
//支付宝支付策略
public class AliPayPayStrategyImpl implements PayStrategy{
    @Override
    public void pay(Map<String, Object> paramsMap) {
        System.out.println("支付宝支付");
        System.out.println("用户:"+paramsMap.get("uid")+"支付完成。支付金额:"+paramsMap.get("money"));
    }
}


package com.example.study.strategy;

import java.util.Map;
//微信支付策略
public class WechatPayStrategyImpl implements PayStrategy{
    @Override
    public void pay(Map<String, Object> paramsMap) {
        System.out.println("微信支付");
        System.out.println("用户:"+paramsMap.get("uid")+"支付完成。支付金额:"+paramsMap.get("money"));
    }
}

定义环境类

package com.example.study.strategy;

import java.util.Map;
//环境类
public class PayContext {
    //持有策略类的引用
    private PayStrategy payStrategy;
    
    public void payInvoke(Map<String,Object> paramsMap){
        payStrategy.pay(paramsMap);
    }
    
    public PayStrategy getPayStrategy() {
        return payStrategy;
    }
    //当前环境选择哪种策略
    public void setPayStrategy(PayStrategy payStrategy) {
        this.payStrategy = payStrategy;
    }
}

最后是客户端,调用入口

package com.example.study.strategy;

import java.util.HashMap;
import java.util.Map;

public class StrategyClient {

    public static void main(String[] args) {
        Map<String,Object> paramsMap = new HashMap<>();
        paramsMap.put("uid","2088xxxxxxxx");
        paramsMap.put("money","100");

        //实际开发-动态生成环境类对象。
        //支付宝支付策略
        PayContext aliPayContext = AliPayContext();
        aliPayContext.payInvoke(paramsMap);
        //实际开发-动态生成环境类对象。
        //微信支付策略
        PayContext wechatContext = WechatContext();
        wechatContext.payInvoke(paramsMap);
    }

   static PayContext AliPayContext(){
        PayContext payContext = new PayContext();
        PayStrategy payStrategy = new AliPayPayStrategyImpl();
        payContext.setPayStrategy(payStrategy);
        return payContext;
    }
    static PayContext WechatContext(){
        PayContext payContext = new PayContext();
        PayStrategy payStrategy = new WechatPayStrategyImpl();
        payContext.setPayStrategy(payStrategy);
        return payContext;
    }
}

调用结果
在这里插入图片描述
如果我想新增一个银联的支付方式。那么只需要新增对应的银联策略实现类。然后客户端在调用支付时构建银联策略就行

package com.example.study.strategy;

import java.util.Map;

public class UnionPayStrategyImpl implements PayStrategy{
    @Override
    public void pay(Map<String, Object> paramsMap) {
        System.out.println("银联支付");
        System.out.println("用户:"+paramsMap.get("uid")+"支付完成。支付金额:"+paramsMap.get("money"));
    }
}


//client新增银联策略构建
 static PayContext UnionPayContext(){
        PayContext payContext = new PayContext();
        PayStrategy payStrategy = new UnionPayStrategyImpl();
        payContext.setPayStrategy(payStrategy);
        return payContext;
    }

调用结果:
在这里插入图片描述
可以看到,使用策略模式非常易于扩展,符合开闭原则。另外策略模式在结构上跟简单工厂模式有点类似。策略抽象类相当于产品抽象类、策略实现类相当于具体产品、环境类相当于工厂类。虽然结构角色相似,但工厂模式是属于创建型模式,用来创建对象的。而策略模式属于对象行为模式。是用来描述对象行为的,即如何使用对象。

上面的演示是策略模式最基本的使用。环境类只单独引用一个种策略。即每个不同的策略都需要构建不同的环境类。实际开发当中,可以将其优化一下:环境类持有多个策略的引用。使用时根据不同的条件选择不同的策略

进阶演示

优化后的环境类

package com.example.study.strategy;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class UpgradePayContext {
    private Map<String,PayStrategy> strategyMap = new ConcurrentHashMap();

    public UpgradePayContext (){
        //添加策略实际开发可动态配置:比如读取配置文件、读取数据库、读取统一配置中心配置等等
        strategyMap.put("alipay",new AliPayPayStrategyImpl());
        strategyMap.put("wechat",new WechatPayStrategyImpl());
        strategyMap.put("unionPay",new UnionPayStrategyImpl());
    }
    
    public void payInvoke(Map<String,Object> paramsMap){
        PayStrategy payStrategy = strategyMap.get(paramsMap.get("strategyKey"));
        payStrategy.pay(paramsMap);
    }

    //获取策略
    PayStrategy getStrategy(String key){
       return strategyMap.get(key);
    }
    //新增策略
    void addStrategy(String key,PayStrategy payStrategy){
        strategyMap.put(key,payStrategy);
    }
    //删除策略
    void removeStrategy(String key){
        strategyMap.remove(key);
    }
}

客户端调用

package com.example.study.strategy;

import java.util.HashMap;
import java.util.Map;

public class StrategyClient {

    public static void main(String[] args) {
        Map<String,Object> paramsMap = new HashMap<>();
        paramsMap.put("uid","2088xxxxxxxx");
        paramsMap.put("money","100");

        UpgradePayContext upgradePayContext = new UpgradePayContext();
        //支付宝支付
        paramsMap.put("strategyKey","alipay");
        upgradePayContext.payInvoke(paramsMap);

        //微信支付
        paramsMap.put("strategyKey","wechat");
        upgradePayContext.payInvoke(paramsMap);

        //银联支付
        paramsMap.put("strategyKey","unionPay");
        upgradePayContext.payInvoke(paramsMap);
    }
}

运行结果
在这里插入图片描述
优化过后使用起来更加方便,代码也更加简洁。

总结

以上就是对策略模式的概念以及用法的介绍。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/99034.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!