首页 > 其他分享 >设计模式--策略模式

设计模式--策略模式

时间:2023-08-14 22:55:50浏览次数:30  
标签:return 策略 -- commonUtils 模式 new 设计模式 public String

简介

策略模式是一种行为设计模式,它将一组行为转换为对象,并使其在原始上下文对象内部能够相互替换

  • 原始对象被称为上下文,它包含指向策略对象的引用并将执行行为的任务分派给策略对象

组成

  • 策略接口(Strategy):所有具体策略的通用接口,它声明了一个上下文用于执行策略的方法
  • 具体策略(Concrete Strategies):实现上下文所用算法的各种不同变体
  • 上下文(Context):维护指向具体策略的引用,且仅通过策略接口与该对象进行交流
  • 客户端(Client):创建一个特定策略对象并将其传递给上下文。上下文则会提供一个设置器以便客户端在运行时替换相关联的策略

案例:策略模式被用于在电子商务应用中实现各种支付方法(信用卡、支付宝、微信支付),具体策略不仅会完成实际的支付工作。如果不使用策略模式,则会出现使用if else 判断具体的支付方式,对后续的新增和修改不符合开闭原则。


实现方式

策略接口

将支付的行为抽象为一个策略接口

public interface PaymentStrategy {

    /**
     * 支付
     */
    boolean payment(BigDecimal amount);
}

具体策略的实现

public class PayByCreditCard implements PaymentStrategy{

    @Override
    public boolean payment(BigDecimal amount) {
        //信用卡支付逻辑
        System.out.println("信用卡支付逻辑");
        return true;
    }
}
public class PayByWechatPayment implements PaymentStrategy{

    @Override
    public boolean payment(BigDecimal amount) {
        //微信支付逻辑
        System.out.println("微信支付逻辑");
        return true;
    }
}
public class PayByAliPayment implements PaymentStrategy{

    @Override
    public boolean payment(BigDecimal amount) {
        //支付宝支付逻辑
        System.out.println("支付宝支付逻辑");
        return true;
    }
}

上下文对象

public class PaymentContext {

    private final PaymentStrategy paymentStrategy;

    public PaymentContext(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }

    public boolean payment(BigDecimal amount) {
        return paymentStrategy.payment(amount);
    }
}

客户端

public class Main {

    public static void main(String[] args) {
        PaymentContext creditCard = new PaymentContext(new PayByCreditCard());
        creditCard.payment(new BigDecimal(10));

        PaymentContext aliPayment = new PaymentContext(new PayByAliPayment());
        aliPayment.payment(new BigDecimal(10));

        PaymentContext wechatPayment = new PaymentContext(new PayByWechatPayment());
        wechatPayment.payment(new BigDecimal(10));
    }
}

项目中使用

在进行企业微信内部应用开发时,应用可以接收成员发送的信息,信息格式包括:文本、图片、语音、视频、位置、链接。每种消息的格式都有不同的处理方式,根据消息的类型进行区分选择对应的策略进行处理即可。具体的UML如下

消息策略接口

public interface MessageStrategy {

    /**
     * 处理消息
     * @param chat 解密后的明文信息
     * @return 被动返回的内容
     */
    String handleMessage(ChatDto chat);
}

具体策略实现

@Slf4j
@Component("image")
public class ImageMsgStrategy implements MessageStrategy {

    private final CommonUtils commonUtils;

    public ImageMsgStrategy(CommonUtils commonUtils) {
        this.commonUtils = commonUtils;
    }

    @Override
    public String handleMessage(ChatDto chat) {

        CompletableFuture<Response> future = CompletableFuture.supplyAsync(() -> {
            //图片消息的处理逻辑
            log.info("接收到用户发送的图片消息为:" + chat.getMsg());
            return Response.builder().data(Data.builder().data("image msg").build()).build();
        });

        //处理完后,返回信息给到企业微信推送给到具体的用户
        future.thenAccept(response -> commonUtils.writeResponse(response, chat));

        //被动回复
        return "";
    }
}
@Slf4j
@Component("voice")
public class VoiceMsgStrategy implements MessageStrategy {

    private final CommonUtils commonUtils;

    public VoiceMsgStrategy(CommonUtils commonUtils) {
        this.commonUtils = commonUtils;
    }

    @Override
    public String handleMessage(ChatDto chat) {

        CompletableFuture<Response> future = CompletableFuture.supplyAsync(() -> {
            //语音消息的处理逻辑
            log.info("接收到用户发送的语音消息为:" + chat.getMsg());
            return Response.builder().data(Data.builder().data("voice msg").build()).build();
        });

        //处理完后,返回信息给到企业微信推送给到具体的用户
        future.thenAccept(response -> commonUtils.writeResponse(response, chat));

        //被动回复
        return "";
    }
}
@Slf4j
@Component("text")
public class TextMsgStrategy implements MessageStrategy {

    private final CommonUtils commonUtils;

    public TextMsgStrategy(CommonUtils commonUtils) {
        this.commonUtils = commonUtils;
    }

    @Override
    public String handleMessage(ChatDto chat) {

        CompletableFuture<Response> future = CompletableFuture.supplyAsync(() -> {
            //文本消息的处理逻辑
            log.info("接收到用户发送的文本消息为:" + chat.getMsg());
            return Response.builder().data(Data.builder().data("text msg").build()).build();
        });

        //处理完后,返回信息给到企业微信推送给到具体的用户
        future.thenAccept(response -> commonUtils.writeResponse(response, chat));

        //被动回复
        return "";
    }
}

上下文对象

@Component
public class MessageContext {
    
    @Resource
    private Map<String,MessageStrategy> messageStrategyMap = new ConcurrentHashMap<>();
    
    public MessageStrategy getMessageStrategy(String msgType) {

        if (!StringUtils.hasText(msgType)) {
            throw new NullPointerException("msgType 消息类型为空");
        }

        MessageStrategy strategy = messageStrategyMap.get(msgType);
        if (Objects.isNull(strategy)) {
            throw new NullPointerException(String.format("不存在消息类型为:%s 的策略", msgType));
        }

        return strategy;
    }
}

 测试使用

@GetMapping(value = "/msg")
public @ResponseBody Response<String> msg(@RequestParam(value = "agentId") String agentId,
                                          @RequestParam(value = "fromUser") String fromUser,
                                          @RequestParam(value = "msgType") String msgType) {

    ChatDto chatDto = new ChatDto();
    chatDto.setAgentId(agentId);
    chatDto.setFromUser(fromUser);
    chatDto.setMsgType(msgType);

    MessageStrategy strategy = messageContext.getMessageStrategy(chatDto.getMsgType());
    String msg = strategy.handleMessage(chatDto);

    return Response.ok(msgType + " success" + msg);
}

优势和缺点

优势

  • 将算法的实现和使用算法的代码隔离开来
  • 符合开闭原则。无需对上下文进行修改即可引入新的策略

缺点

  • 如果算法极少发生改变,引入策略模式会使程序过于复杂
  • 客户端必须知道策略间的不同——它需要选择合适的策略

使用场景

  • 当想使用对象中各种不同的算法变体, 并希望能在运行时切换算法时, 可使用策略模式
  • 当有许多仅在执行某些行为时略有不同的相似类时, 可使用策略模式

Java 中使用案例

  • java.util.Comparator#compare的调用来自Collections#sort()

识别方法: 策略模式可以通过允许嵌套对象完成实际工作的方法以及允许将该对象替换为不同对象的设置器来识别

标签:return,策略,--,commonUtils,模式,new,设计模式,public,String
From: https://www.cnblogs.com/52-IT-y/p/17628609.html

相关文章

  • EQ-BDS面板部署QQ机器人
    一、名词解释二、配置教程0.预处理1.解压压缩包2.运行配置程序3.生成配置4.运行启动脚本5.扫码登录6.部署到服务器三、EQ-BDS面板配置机器人教程1.复制插件token2.设置面板连接插件3.确认是否连接成功4.配置群号5.权限设置后续升级机器人的方法一、名词解......
  • operator bool 函数
    title:"operatorbool函数"date:2023-08-14T16:05:25+08:00tags:["C++"]categories:[]draft:false参考文档user-definedconversionfunction-cppreference.comTheSafeBoolIdiom-知乎为什么operatorbool()需要用explicit修饰?c++-Whydoesdecl......
  • java_房屋出租系统
    1架构graphLR;service业务层;utils常用工具;RentAPP入口-->主菜单;主菜单-->房屋列表界面--调用-->list方法;主菜单-->新增界面--调用-->add方法;主菜单-->删除界面--调用-->del方法;主菜单-->修改界面--调用-->mod方法;主菜单-->查找界面--调用......
  • 问题--连接超时
    1.问题sqlalchemy.exc.OperationalError:(pymysql.err.OperationalError)(2003,"Can'tconnecttoMySQLserveron'113.54.246.60'(timedout)")(Backgroundonthiserrorat:https://sqlalche.me/e/20/e3q8)2.解决这个错误提示是SQLAlchemy和pymysq......
  • js判断多条件
     if((String(properties.SYDMC).includes(String(attributeValue))||String(properties.SYDMC)==String(attributeValue))&&(String(properties.AnotherField).includes(String(anotherAttributeValue))||String(properties.A......
  • 废柴英语在中文中通常翻译为"useless English"或"rubbish English"
    废柴英语怎么说提问者:u627050 最后回答时间:2023-01-31废柴英语在中文中通常翻译为"uselessEnglish"或"rubbishEnglish"。它指的是不流利或不准确的英语表达。这个词的来源可能源于把英语作为一种废物或无用之物的看法。下面是一些英文例句及其中文翻译:"MyEnglishisreallyba......
  • 第五章 Gateway--服务网关
    5.1网关简介大家都都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调用。 这样的架构,会存在着诸多的问题:客户端多次请求不同的微服务,增加客户端代码或......
  • QT画图
    重点:每个QWidget都自带的功能,继承了QPainteDevice都可以使用QPainter来进行绘图。我们需要调用paintEvent绘制事件,这个事件QWidget这个类自带的事件。重写这个事件:如果父类有某个办法,此时这个子类需要有一个更跟父类同样方法名称的。实例化对象写法:QQPainterpainter(this);//......
  • 20230813 arm64 汇编学习 helloworld.s
    Programming with64-Bit ARMAssembly Language SingleBoardComputerDevelopment forRaspberryPiandMobileDevices —StephenSmith 32bitsARM64指令:////Assemblyprogramtoprint"helloworld"tostdout////x0-x2parameterstolinuxfunct......
  • nacos集群部署
    准备nacos一般集群需要至少3个节点。我们先准备3台机器: 192.168.11.200、192.168.11.196、192.168.11.126nacos的默认服务端口是8848,但是由于我们的机器上还有其他nacos服务正在作用,所以,我们这里把端口改为8748,如下:192.168.11.200:8748192.168.11.196:8748192.168.11.......