0
点赞
收藏
分享

微信扫一扫

Java策略模式的基本使用

贵州谢高低 2022-03-16 阅读 31

Java策略模式的基本使用

本文有引用两个网址:
Java策略模式基本使用
设计模式应用之策略模式

一、简介

1.定义

	策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
	策略这个词应该怎么理解,打个比方说,我们出门的时候会选择不同的出行方式,比如骑自行车、坐公交、坐火车、坐飞机、坐火箭等等,这些出行方式,每一种都是一个策略。 再比如我们去逛商场,商场现在正在搞活动,有打折的、有满减的、有返利的等等,其实不管商场如何进行促销,说到底都是一些算法,这些算法本身只是一种策略,并且这些算法是随时都可能互相替换的,比如针对同一件商品,今天打八折、明天满100减30,这些策略间是可以互换的。 策略模式(Strategy),定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换。

二、应用场景

1、业务场景 现在需要接收来自某系统的回调,消息回调会有很多类型,比如私聊文本消息、私聊图片消息、新好友申请、私聊语音消息等,每一种消息类型,对应不同的逻辑处理,我们最开始是想直接if-else或者switch,走不同的分支逻辑搞定,但是这样扩展性不好,不易维护,这时我们想到了策略模式。

2、业务中一些用户需求变化的定制,比如 这个用户需要对广州的航班进行业务处理,另一个用户需要对厦航的航班进行特殊的处理(定制话,根据用户到需求来写对应的业务)。

3、 容错恢复机制是应用程序开发中非常常见的功能。那么什么是容错恢复呢?简单点说就是:程序运行的时候,正常情况下应该按照某种方式来做,如果按照某种方式来做发生错误的话,系统并不会崩溃,也不会就此不能继续向下运行了,而是有容忍出错的能力,不但能容忍程序运行出现错误,还提供出现错误后的备用方案,也就是恢复机制,来代替正常执行的功能,使程序继续向下运行。
举个实际点的例子吧,比如在一个系统中,所有对系统的操作都要有日志记录,而且这个日志还需要有管理界面,这种情况下通常会把日志记录在数据库里面,方便后续的管理,但是在记录日志到数据库的时候,可能会发生错误,比如暂时连不上数据库了,那就先记录在文件里面,然后在合适的时候把文件中的记录再转录到数据库中。
对于这样的功能的设计,就可以采用策略模式,把日志记录到数据库和日志记录到文件当作两种记录日志的策略,然后在运行期间根据需要进行动态的切换。

三、基础使用

1、定义一个出参结果类

用来返回出去

@Data
public class SendResult {

    public SendResult(Boolean result, String message) {
        this.result = result;
        this.message = message;
    }
	// 状态
    private Boolean result;
    // 消息
    private String message;
}

2、定义枚举类 – 根据业务需求可要可不要

@Getter
public enum MsgCallBackEnum {
    //新好友申请
    NEWFRIEND_MSG_CALL_BACK(0, "newFriendMsgCallBackHandler"),
    //添加好友成功
    ADDFRIENDSUCCESS_MSG_CALL_BACK(16, "addfriendSuccessMsgCallBackHandler"),
    //私聊文本消息
    PRIVATECHATTEXT_MSG_CALL_BACK(5, "privateChatTextMsgCallBackHandler"),
    //私聊图片消息
    PRIVATECHATIMAGE_MSG_CALL_BACK(6, "privateChatImageMsgCallBackHandler"),
    //私聊视频消息
    privateChatVIDEO_MSG_CALL_BACK(7, "privateChatVideoMsgCallBackHandler"),
    //私聊语音消息
    PRIVATECHATVOICE_MSG_CALL_BACK(8, "privateChatVoiceMsgCallBackHandler");

    private Integer type;
    private String beanName;

    MsgCallBackEnum(Integer type, String beanName) {
        this.type = type;
        this.beanName = beanName;
    }

    public static String getBeanName(Integer type) throws BusinessException {
        for (MsgCallBackEnum msgCallBackStrategyEnum : MsgCallBackEnum.values()) {
            if (msgCallBackStrategyEnum.type.equals(type)) {
                return msgCallBackStrategyEnum.getBeanName();
            }
        }
        return null;
    }

}

2、定义一个接口

统一定义一个处理需求的方法,一个用来判断是否支持的方法

public interface OpenApi {

    /**
     * 校验当前接口是否支持
     *
     * @param url 接口请求路径
     * @return
     */
    boolean support(String uri);

    /**
     * 对外执行方法
     *
     * @param url    接口请求路径
     * @param result 返回结果
     * @return
     */
    SendResult handle(String url, Object[] result);
}

3、定义抽象类

抽象类定义抽象方法 handle,每一种逻辑处理类只需要继承这个抽象类就可以了。

public abstract class AbstractOpenApi implements OpenApi {

    /**
     * 对外执行方法
     *
     * @param uri    ws请求地址
     * @param result 返回结果
     * @return
     */
    @Override
    public SendResult handle(String uri, Object[] result) {
        return getResult(uri, result);
    }

    /**
     * 自己实现方法
     *
     * @param uri
     * @param result
     * @return
     */
    public abstract SendResult getResult(String uri, Object[] result);
}

4.定义实现类

实现类具体处理业务逻辑,继承抽象类

@RefreshScope
@Service
@Slf4j
public class ResultApi1 extends AbstractOpenApi {

    /*@Value(value = "${wsResultApi1}")
    private String URL;*/
    
    private final static String URL = "http://127.0.0.1:8080";

    /**
     * 自己实现方法
     *
     * @param url
     * @param result
     * @return
     */
    @Override
    public SendResult getResult(String url, Object[] result) {

        log.info("业务处理1类");
        // JSON 转换
        JSONObject jsonObject = (JSONObject) JSONObject.parse(result[0].toString());
		// 获取 JSON 转换后的值并返回出去
        return new SendResult(jsonObject.getBoolean("Statue"),
                jsonObject.getString("Messages"));
    }

    /**
     * 校验当前接口
     *
     * @param url
     * @return
     */
    @Override
    public boolean support(String url) {
        return URL.equals(url);
    }
}

5、测试类

package com.xx.send.ws;

import com.xx.send.SendApp;
import com.xx.send.ws.handle.WsResultHandleMangers;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

/**
 * ws接口处理测试类
 *
 * @Date 2022/3/14 20:34
 * @Version 1.0
 */
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SendApp.class)
public class WsResultTest {

    @Resource
    private WsResultHandleMangers wsResultHandleMangers;

    public static final String URL = "http://172.26.145.45:8081";

    @Test
    public void wsTest() {
        String message1 = "{\"Statue\":false,\"Messages\":\"解析失败!\"}";
        String message2 = "{\"Statue\":true,\"Messages\":\"解析成功!\"}";
        Object[] messages = new String[]{message2};
        wsResultHandleMangers.handle(URL, messages);
        log.info("=====" + message2);
    }
}

四、测试结果

结果:
在这里插入图片描述

五、总结

1.何时使用 一个系统有许多类,而区分它们的只是他们直接的行为时
2.方法 将这些算法封装成一个一个的类,任意的替换
3.优点 算法可以自由切换 避免使用多重条件判断(如果不用策略模式我们可能会使用多重条件语句,不利于维护) 扩展性良好,增加一个策略只需实现接口即可
4.缺点 策略类数量会增多,每个策略都是一个类,复用的可能性很小 所有的策略类都需要对外暴露
5.使用场景 多个类只有算法或行为上稍有不同的场景 算法需要自由切换的场景 需要屏蔽算法规则的场景

举报

相关推荐

0 条评论