Java 设计模式中的策略模式详情

 更新时间:2022年09月25日 10:58:10   作者:我赢了算我输  
这篇文章主要介绍了Java 设计模式中的策略模式详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下

策略模式的应用场景

策略模式是否要使用,取决于业务场景是否符合,有没有必要。

是否符合

如果业务是处于不同的场景时,采取不同的处理方式的话,就满足符合。 这里举几个业务栗子

如果今天我有1000块,那我就和朋友去游乐园玩、然后再去吃顿好吃的。如果有2000块的话,那我就先买一件好看的衣服,再和朋友去游乐园玩和吃好吃的商品收银业务,根据店中不同的活动分为正常收费、折扣收费、返利收费,每种收费的方式都不一样接收某安全设备的数据的时候,根据发过来不同的数据类型,执行设备报警、设备指定信息存储、设备本身状态信息修改等等的处理方式

这里上面三种业务场景都符合处于不同的场景时,采取不同的处理方式

有没有必要

这里等描述完例子后,再回到这个问题

例子

这里采用上面第三个例子的业务分别进行编写不用策略模式和用策略模式的效果

不用策略模式

public class Main {
    public static void main(String[] args) {
        //设备报警
        int deviceDataType=2;
        DeviceData deviceData=new DeviceData();
        deviceData.setName("安全设备A");

        switch (deviceDataType){
            case 1:
                DeviceCallPolice(deviceData);
                break;
            case 2:
                DeviceStatus(deviceData);
                break;
            default:
                System.out.println("没有相关的策略");
                break;
        }

    }
    private static void DeviceStatus(DeviceData deviceData) {
        System.out.println("正在修改"+deviceData.getName()+"状态为指定状态");
        System.out.println("正在记录本次修改状态的时间信息");
        System.out.println("根据修改后的状态判断是否要通知相关人");
    }
    private static void DeviceCallPolice(DeviceData deviceData) {
        System.out.println("正在修改"+deviceData.getName()+"状态为报警状态");
        System.out.println("正在记录本次报警时间信息");
        System.out.println("设备相关人的短信通知");
    }

}

效果:

使用策略模式

策略上下文

/**
 * 
 * 安全设备处理上下文
 */
public class SafetyDeviceContext {

    private DeviceHandlerStrategy deviceHandlerStrategy;

    public SafetyDeviceContext(int dataType){
        switch (dataType){
            case 1:
                deviceHandlerStrategy=new DeviceCallPoliceStrategy();
                break;
            case 2:
                deviceHandlerStrategy=new DeviceStatusStrategy();
                break;
            default:
                System.out.println("没有相关的策略");
                break;
        }

    }
    public void Handler(DeviceData deviceData){

        deviceHandlerStrategy.handler(deviceData);
    }
}

策略接口以及具体实现类

/**
 * 设备处理策略
 */
public interface DeviceHandlerStrategy {

    void handler(DeviceData deviceData);
}
/**
 * 安全设备报警策略
 */
public class DeviceCallPoliceStrategy implements DeviceHandlerStrategy {

    @Override
    public void handler(DeviceData deviceData) {

        System.out.println("正在修改设备状态为报警状态");
        System.out.println("正在记录本次报警时间信息");
        System.out.println("设备相关人的短信通知");
    }
}
/**
 * 设备状态修改策略
 */
public class DeviceStatusStrategy implements DeviceHandlerStrategy {

    @Override
    public void handler(DeviceData deviceData) {
        System.out.println("正在修改设备状态为指定状态");
        System.out.println("正在记录本次修改状态的时间信息");
        System.out.println("根据修改后的状态判断是否要通知相关人");
    }
}

Main类

public class Main {

    public static void main(String[] args) {
        //设备报警
        int deviceDataType=2;
        DeviceData deviceData=new DeviceData();
        deviceData.setName("安全设备A");
        SafetyDeviceContext safetyDeviceContext=new SafetyDeviceContext(deviceDataType);
        safetyDeviceContext.handler(deviceData);
    }
}

效果:

两种方式的不同

从简易和易懂程度来说,自然是不用策略模式好一些,用策略模式会导致类的增多,而且如果不懂策略模式的人去看代码时可读性不高。但使用策略模式胜于可扩展性和可维护性要强于不用策略模式的

使用策略模式在Main函数(使用方),消除了类型的swich判断,把这些判断放到了Context,使用方调用的时候,就不必过多关心设备处理策略,只需要把值传进Context就好了。

之前我很不理解策略模式为什么能避免使用多重条件判断,因为上面的写法只是把判断的代码移到了Context而已,要写的判断还是要写,直到我知道了采用字典和反射的方式时,就理解了,往下会说

  • 如果后续我们要添加一种"设备定时报告信息"业务处理方式时,使用策略模式那种只需要在Context添加一层case(也可以不需要,可以用反射的方式)和添加一个策略的实现类就好了,而不用策略模式需要在原来使用方的代码添加一层case,可能会影响到原来的业务稳定性。
  • 算法独立出来也方便我们使用单元测试进行测试

策略模式有没有必要使用?

策略模式的目的是减少具体的算法方式使用方式之间的耦合,避免多重if判断,并让具体的算法方法尽可能独立。所以实现的时候,必然成本会高一些。因此我们要使用策略模式的时候,要确定该业务业务本身是否复杂,后续是不是会时不时添加其他的处理方式
例如上面的第三个例子,设备对应的处理措施本身具备了复杂性,例如会涉及数据本身的处理、设备状态的更改、设备事件的触发等等处理措施,而且后续因业务的扩展,可能会添加不同的设备场景,不同的设备处理方式。像这种就可以考虑使用

如何避免Context类使用判断逻辑

可以采用字典+反射的方式进行避免

定义策略字典的全局变量

/**
 * 设备处理策略方式字典
 */
public class DeviceStrategyDictionary {
    public static HashMap<Integer,String> dictionary=new HashMap<>();

}

修改Context的代码

import java.util.HashMap;

/**
 * 安全设备处理上下文
 */
public class SafetyDeviceContext {

    private DeviceHandlerStrategy deviceHandlerStrategy;

    public SafetyDeviceContext(int dataType) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        HashMap<Integer,String> dic= DeviceStrategyDictionary.dictionary;
        if(!dic.containsKey(dataType)){
            System.out.println("不包含该处理方式");
        }
        //使用反射的方式
        Class<?> fz=Class.forName(dic.get(dataType));
        deviceHandlerStrategy=(DeviceHandlerStrategy) fz.newInstance();

    }
    public void handler(DeviceData deviceData){

        deviceHandlerStrategy.handler(deviceData);
    }
}

Main方法

public class Main {

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

        //程序启动的时候
        DeviceStrategyDictionary.dictionary.put(1,"DeviceCallPoliceStrategy");
        DeviceStrategyDictionary.dictionary.put(2,"DeviceStatusStrategy");

        //设备报警
        int deviceDataType=2;
        DeviceData deviceData=new DeviceData();
        deviceData.setName("安全设备A");

        SafetyDeviceContext safetyDeviceContext=new SafetyDeviceContext(deviceDataType);

        safetyDeviceContext.handler(deviceData);
    }

}

效果:

这样就可以避免使用if判断了,不过反射也有相关的性能消耗,这点也需要做权衡。

到此这篇关于Java 设计模式中的策略模式详情的文章就介绍到这了,更多相关Java 策略模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解JVM类加载机制及类缓存问题的处理方法

    详解JVM类加载机制及类缓存问题的处理方法

    这篇文章主要给大家介绍了关于JVM类加载机制及类缓存问题的处理方法的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-01-01
  • MyBatis常用标签以及使用技巧总结

    MyBatis常用标签以及使用技巧总结

    在我们的学习过程中,我们经常使用到mybatis,这篇文章主要给大家介绍了关于MyBatis常用标签以及使用技巧的相关资料,需要的朋友可以参考下
    2021-05-05
  • 详解Spring Boot工程集成全局唯一ID生成器 UidGenerator的操作步骤

    详解Spring Boot工程集成全局唯一ID生成器 UidGenerator的操作步骤

    本文就在项目中来集成 UidGenerator这一工程来作为项目的全局唯一 ID生成器。接下来通过实例代码给大家详解详解Spring Boot工程集成全局唯一ID生成器 UidGenerator的操作步骤,感兴趣的朋友一起看看吧
    2018-10-10
  • 解密Spring Boot深入理解条件装配与条件注解

    解密Spring Boot深入理解条件装配与条件注解

    条件注解是一种特殊的注解,用于标记在配置类、组件类或方法上,它们根据某些条件的结果来决定是否应用相应的配置或组件,这篇文章主要介绍了解密Spring Boot深入理解条件装配与条件注解,需要的朋友可以参考下
    2024-06-06
  • RabbitMQ集群运维实践教程

    RabbitMQ集群运维实践教程

    RabbitMQ的集群模式主要有两种普通集群模式和镜像队列模式,下面给大家分享RabbitMQ集群运维实践教程,感兴趣的朋友跟随小编一起看看吧
    2024-03-03
  • 探索Java中private方法添加@Transactional事务未生效原因

    探索Java中private方法添加@Transactional事务未生效原因

    你又遇到过明明给private方法添加了@Transactional但是事务依然没有生效的情况吗,具体原因本篇文章将详细告诉你,有需要的朋友跟着小编往下看吧
    2021-11-11
  • springSecurity用户认证和授权的实现

    springSecurity用户认证和授权的实现

    Spring Security 是一个开源的安全框架,提供了基于权限的访问控制、身份认证的功能,本文主要介绍了springSecurity用户认证和授权,具有一定参考价值,感兴趣的可以了解一下
    2024-04-04
  • mybatis-plus添加数据时id自增问题及解决

    mybatis-plus添加数据时id自增问题及解决

    这篇文章主要介绍了mybatis-plus添加数据时id自增问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java常用占位符方法简单代码实例

    Java常用占位符方法简单代码实例

    占位符是Java中常用的技术,用于在字符串中插入变量值或动态生成字符串,这篇文章主要给大家介绍了关于Java常用占位符方法的相关资料,文中介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • 运行Jar包出现提示xxx中没有主清单属性报错问题解决方法

    运行Jar包出现提示xxx中没有主清单属性报错问题解决方法

    这篇文章主要介绍了运行Jar包出现:xxx中没有主清单属性报错,当出现报错:xxx中没有主清单属性,解决方法也很简单,在pom.xml配置中,加上相应配置即可,需要的朋友可以参考下
    2023-08-08

最新评论