文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-04-02 19:55

关注

策略模式的应用场景

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

是否符合

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

如果今天我有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而已,要写的判断还是要写,直到我知道了采用字典和反射的方式时,就理解了,往下会说

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

策略模式的目的是减少具体的算法方式使用方式之间的耦合,避免多重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 策略模式内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯