精华内容
下载资源
问答
  • 策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换

    1.定义

    策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。

    2.问题

    一天, 你打算为游客们创建一款导游程序。 该程序的核心功能是提供美观的地图, 以帮助用户在任何城市中快速定位。

    用户期待的程序新功能是自动路线规划: 他们希望输入地址后就能在地图上看到前往目的地的最快路线。

    程序的首个版本只能规划公路路线。 驾车旅行的人们对此非常满意。 但很显然, 并非所有人都会在度假时开车。 因此你在下次更新时添加了规划步行路线的功能。 此后, 你又添加了规划公共交通路线的功能。

    而这只是个开始。 不久后, 你又要为骑行者规划路线。 又过了一段时间, 你又要为游览城市中的所有景点规划路线。

    尽管从商业角度来看, 这款应用非常成功, 但其技术部分却让你非常头疼: 每次添加新的路线规划算法后, 导游应用中主要类的体积就会增加一倍。 终于在某个时候, 你觉得自己没法继续维护这堆代码了。

    无论是修复简单缺陷还是微调街道权重, 对某个算法进行任何修改都会影响整个类, 从而增加在已有正常运行代码中引入错误的风险。

    此外, 团队合作将变得低效。 如果你在应用成功发布后招募了团队成员, 他们会抱怨在合并冲突的工作上花费了太多时间。 在实现新功能的过程中, 你的团队需要修改同一个巨大的类, 这样他们所编写的代码相互之间就可能会出现冲突。

    3.代码示例

    假如现在你有一个业务需求,针对四种不同的判断条件,需要选择执行不同的动作。就好比下面的代码

        public static void main(String[] args) {
            int i = (int) (Math.random()*4);
            System.out.println(i);
    
            if(i == 1){
                System.out.println(i*1);
            }else if(i == 2){
                System.out.println(i+1);
            }else if(i == 3){
                System.out.println(i-1);
            }else if(i == 4){
                System.out.println(i*10);
            }
        }
    
    

    代码很简单,大家都可以看懂。那么如果我们要将上面的代码改造成为策略模式该怎么进行?

    首先,我们依据策略模式的定义,定义中表名策略模式之间是可以进行互换的,那我们首先想到的就是使用接口。首先 我们定义策略模式的接口。代码如下:

    public interface IReceiptHandleStrategy {
        void handle(int i);
    }
    

    然后依据我们上面的代码,分别写出对应的实现算法。

    public class OneReceiptHandleStrategy implements IReceiptHandleStrategy{
        @Override
        public void handle(int i) {
            System.out.println(i*1);
        }
    }
    
    public class TwoReceiptHandleStrategy implements IReceiptHandleStrategy{
        @Override
        public void handle(int i) {
            System.out.println(i + 1);
        }
    }
    
    public class ThreeReceiptHandleStrategy implements IReceiptHandleStrategy{
        @Override
        public void handle(int i) {
            System.out.println(i - 1);
        }
    }
    
    public class FourReceiptHandleStrategy implements IReceiptHandleStrategy{
        @Override
        public void handle(int i) {
            System.out.println(i * 10);
        }
    }
    

    可以看到,我们的代码执行的都比较简单,就是相当于把上面的打印写到每一个实现类中。那么接下来,我们需要写一个容器,去封装下面具体的实现类。这个容器要能起到以下的作用,接受策略模式的接口,调用接口的实现方法。代码如下

    public class ReceiptStrategyContext {
        private IReceiptHandleStrategy receiptHandleStrategy;
    
        public void setReceiptHandleStrategy(IReceiptHandleStrategy receiptHandleStrategy) {
            this.receiptHandleStrategy = receiptHandleStrategy;
        }
    
        public void handleReceipt(int i){
            if (receiptHandleStrategy != null) {
                receiptHandleStrategy.handle(i);
            }
        }
    }
    

    那么这些写完了,我们就要考虑如果依据条件去对应正确的实现类。我们很容易可以想到使用map。那么,我们使用简单工厂模式+map。很容易就可以想到下面的代码:

    public class ReceiptHandleStrategyFactory {
    
        private static Map<Integer,IReceiptHandleStrategy> receiptHandleStrategyMap;
    
        static {
            receiptHandleStrategyMap = new HashMap<>();
            receiptHandleStrategyMap.put(1,new OneReceiptHandleStrategy());
            receiptHandleStrategyMap.put(2,new TwoReceiptHandleStrategy());
            receiptHandleStrategyMap.put(3,new ThreeReceiptHandleStrategy());
            receiptHandleStrategyMap.put(4,new FourReceiptHandleStrategy());
        }
        private ReceiptHandleStrategyFactory(){
    
        }
    
        public static IReceiptHandleStrategy getReceiptHandleStrategy(int i){
            return receiptHandleStrategyMap.get(i);
        }
    }
    

    可以看到,工厂模式里面,map的key值就是对应的判断条件。然后我们修改我们的业务代码

    public class CelueFirst {
        public static void main(String[] args) {
            int i = (int) (Math.random()*4);
            System.out.println(i);
            ReceiptStrategyContext receiptStrategyContext = new ReceiptStrategyContext();
            receiptStrategyContext.setReceiptHandleStrategy(ReceiptHandleStrategyFactory.getReceiptHandleStrategy(i));
            receiptStrategyContext.handleReceipt(i);
    
    
            /*if(i == 1){
                System.out.println(i*1);
            }else if(i == 2){
                System.out.println(i+1);
            }else if(i == 3){
                System.out.println(i-1);
            }else if(i == 4){
                System.out.println(i*10);
            }*/
        }
    }
    

    看到这里大家应该可以看到策略模式的好处了,假如现在我需要再额外添加一个条件,之前的代码是在if-else中再添加一个分支,使用策略模式的话。我们就需要再写一个实现类,然后再工厂方法里添加一下就可以了。就是这么简单,而且符合开闭原则,如果需要新增,我们就不需要再去动业务的代码。

    4.总结

    但是有人可能会说了,我觉得一点也不简单,写那么多的类和接口,不麻烦吗?而且我们开发使用的都是Controller-Service-Dao三层 怎么可能新建那么多类?这问题问题的好,说的对。我们实际开发中,是不能使用策略模式替换if-else的 因为不值得。但是这并不代表我们开发中不使用策略模式。其中有一个人说的非常好。
    在这里插入图片描述

    我们只写业务代码确实不用考虑这些。但是如果涉及到一个全新的业务场景,我们在设计的时候,是可以考虑加入设计模式的。

    展开全文
  • 这里写自定义目录标题使用策略模式 + 工厂替换过多的IF ELSE新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一适合你的列表创建一表格设定...

    项目中的痛点

    	项目中存在一个任务中的逻辑,有GO语言转成的Java的微服务工厂,学习任务部分,涉及太多业务的耦合,
    需要根据学习任务类型、科目、业务线区分,各自存在自己的逻辑,一直以来的实现方式是使用if else
    的方式实现,存在一个很大隐患,不熟悉的同事修改一个地方,就影响到了其他的业务线。这里急需一个更加
    优雅的实现方式。
    

    定义策略模式接口

    /**
     * 学习任务策略模式接口
     * @date 2020年3月19日
     */
    public interface FeedStrategy {
    
    	/**
    	 * 生成FeedContent的执行的方法,根据具体类型执行对应子类的方法,
    	 * 所以实际实现中会执行对应子类的方法
    	 * @return
    	 */
    	public PushBeanDto genFeedPush(Content content, JPushCurriculumVO curriculumVo); 
    }
    

    具体学习任务类型实现任务基本策略接口

    /**
     * 课前预习策略
     * @date 2020年3月19日
     */
     public class FeedKQYXStrategy implements FeedStrategy {
    	@Override
    	public PushBeanDto genFeedPush(Content content, JPushCurriculumVO curriculumVo) {
    		PushBeanDto pushBean = new PushBeanDto();
    		// do something for yourself star
    		
    		// do something for yourself end
    		return pushBean;
    	}
    }
    

    学习任务策略工厂类

    /**
     * 学习任务策略工厂类
     * 
     * @date 2020年3月19日
     */
    @Slf4j
    public class FeedStrategyFoctory {
    	public static FeedStrategy getStrategy(FeedTypeEnum typeEnum){
    		FeedStrategy strategy = null;
    		try {
    			String className = FeedStrategyEnum.getClassNameById(typeEnum.getId());
    			log.info("Feed Push getStrategy className={}", className);
    			strategy = (FeedStrategy) Class.forName(className).newInstance();
    		} catch (Exception e) {
    			log.warn("生成学习任务推送信息失败, ", e);
    		}
    		
    		return strategy;
    	}
    }
    
    
    /**
     * 用枚举类来存放具体的学习任务类型和对应的实现策略类的绑定关系
     */
     enum FeedStrategyEnum { 
    	STRATEGY_KHZY(FeedTypeEnum.NOTICE_KHZY.getId(),"com.xxx.app.strategy.feed.FeedKHZYStrategy"),
    	STRATEGY_KQYX(FeedTypeEnum.NOTICE_KQYX.getId(),"com.xxx.app.strategy.feed.FeedKQYXStrategy"),;
    
    	private String id;
        private String className;
        
    	public String getId() {
    		return id;
    	}
    
    	public String getClassName() {
    		return className;
    	}
    
    	FeedStrategyEnum(String id, String className){
    		this.id = id;
    		this.className = className;
    	}
    	
    	public static String getClassNameById(String id){
    		if(StringUtils.isNotBlank(id)){
    			for (FeedStrategyEnum e : FeedStrategyEnum.values()) {
    				if(e.id.equals(id)){
    					return e.getClassName();
    				}
    			}
    		}
    		
    		return null;
    	}
    }
    
    

    建立Facade类,并使用Spring进行管理

    /**
     * 学习任务推送信息Facade, 分离推送策略生成与业务
     * 代码,实现与业务代码逻辑分离,降低耦合度,策略边和业务
     * 变化都不需要修改业务代码
     * 
     * @date 2020年3月19日
     */
    @Component
    public class FeedStrategyFacade {
    	
    	/**
    	 * 执行具体的逻辑
    	 * @param typeEnum
    	 * @param content
    	 * @param curriculumVo
    	 * @return
    	 */
    	public PushBeanDto doGenFeedPush(FeedTypeEnum typeEnum,Content content, JPushCurriculumVO curriculumVo){
    		PushBeanDto pushBean = null;
    		FeedStrategy strategy = FeedStrategyFoctory.getStrategy(typeEnum);
    		if(strategy != null){
    			pushBean = strategy.genFeedPush(content, curriculumVo);
    		} else {
    			pushBean = new PushBeanDto();
    		}
    		
    		return pushBean;
    	}
    }
    

    具体调用的地方

    @Autowired
    private FeedStrategyFacade feedStrategyFacade;
    
    feedStrategyFacade.doGenFeedPush(feedTypeEnum, content, curriculumVo);
    
    展开全文
  • 的弊端在于:不利于对程序的扩展,如果新添加一个功能,那么就得去修改程序再添加一个if...else...分支,根据“开-闭原则”的宗旨:对扩展开放,对修改关闭。后面就想到使用工厂模式+策略模式替代,具体实现细节直接...

          根据项目实际需要,根据实体类业务类型字段进行不同操作,首先想到的是使用if..else,但是项目中使用if...else...的弊端在于:不利于对程序的扩展,如果新添加一个功能,那么就得去修改程序再添加一个if...else...分支,根据“开-闭原则”的宗旨:对扩展开放,对修改关闭。后面就想到使用工厂模式+策略模式替代,具体实现细节直接上代码:

    首先定义一个策略制票服务接口:

    接着不同分支实现该策略接口:

     

           

    最后用工厂模式生成不同策略

    调用端代码:

    展开全文
  • 替换项目中的if-else方法(工厂模式+策略模式)
    展开全文
  • 反射+策略模式替换 if-else 因为最近在做项目的时候经常会遇到很if- else的判断, 想改一下代码 所以就来学习一下 替换掉项目中的判断,好了开始上代码。 1. 使用反射加策略模式之前的代码 if...
  • 什么是策略模式 策略模式(Strategy Pattern)是指...同一系统中存在不同的逻辑算法,而彼此之间在不同场景中需要实现动态替换,如:支付方式,可以选择:支付宝,微信,银联等,彼此之间就可以相互替换,再如商...
  • 策略模式 在策略模式(Strategy Pattern)中,一类的行为或其算法可以在运行时更改。...意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。 主要解决:在有多种算法相似的情况下,使用 ...
  • 但是,一旦该类中有多个条件检查所基于的字段,该基本解决方案便会开始崩溃。 我们将研究一些有关如何使用这些可能性的想法。 有很多方法可以解决,因此我们将从最简单到最困难的工作,始终使用简单的示例来尽...
  • 在实际项目中相信大家都遇到过令人糟心的代码,一方法一溜下来全是if else,还写满了业务逻辑,代码如下: public static void main(String[] args) { String name = "张三"; if("张三".equals(name)){ // ...
  • 但是,一旦类中有多个条件检查所基于的字段,该基本解决方案便会开始崩溃。 我们将研究一些有关如何使用这些可能性的想法。 有很多方法可以解决,因此我们将从最简单到最困难的工作,始终使用简单的示例来尽可能...
  • 优雅的替换if-else语句

    万次阅读 多人点赞 2020-03-18 23:09:30
    场景 日常开发,if-else语句写的不少吧??当逻辑分支非常的时候,if-else套了一层又一层,虽然业务功能倒是实现了,但是看起来是真的很不优雅,尤其是对于我这种有... 采用策略模式+工厂模式; 结合注解,锦...
  • 设计模式之策略模式–配合工厂模式灵活替换不同算法实现 策略模式是一种对可替换的算法或者业务逻辑进行封装,灵活替换模式。 定义了算法家族并分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会...
  • 替换掉 多层 if else 嵌套方法: 1、接口分层 2、多态 3、使用 map 代替分支语句 4、策略+工厂模式 模拟场景:不同的渠道类型分别使用不同的逻辑处理。 渠道类型:储蓄卡、信用卡、公众号 一般实现: public ...
  • 一般来说我们正常的后台管理系统都有所谓的角色的概念,不同管理员权限不一样, 能够行使的操作也不一样,比如: ...传统的判断方法是一串的if else 代码臃肿 传统方式的if else判断 package com.ru...
  • Java中多个ifelse语句的替代设计

    千次阅读 2019-05-27 07:20:36
    我们经常遇到涉及很条件的业务逻辑,并且每逻辑都需要不同的处理方式。以Calculator类为例。我们将有一方法,它接受两数字和一运算符作为输入,并根据操作返回结果: public int calcul...
  • 资源替换工具,旧模型替换新模型,替换GUID,替换meta文件,文件丢失等问题使用说明如何使用 使用说明 第一次写,不是很规范,好东西分享给大家,学点编辑器扩展好处啊! 如何使用 这小工具确实帮到我了,替我省了不少...
  • 正文 业务场景:根据条件判断调用支付宝,微信,或其他第三方支付; if(type==1){ ...如果还有更的支付类型,就在后面使用else if()这也太那啥了吧。。。 代码 公共代码 AliPayStrategy /** * @auth...
  • Android中的工厂模式(减少if-esle和switch-case)
  • 当逻辑分支非常的时候,if-else套了一层又一层,虽然业务功能倒是实现了,但是看起来是真的很不优雅,尤其是对于我这种有强迫症的程序"猿",看到这么多if-else,脑袋瓜子就嗡嗡的,总想着解锁新姿势:干掉过多的if...
  • 一、前提 ...使用Spring的工厂管理+策略模式可以很好的解决这问题。 二、策略模式的介绍 策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每.
  • 来源:love1024.blog.csdn.net/article/details/104955363场景日常开发,if-else语句写的不少吧??当逻辑分支非常的时候,if-else...
  • 工厂 + 策略 toMap 效果 后续 前言 避免过多if - else的新姿势:卫语句、小函数、多态、反射 在之前文章说到,简单 if-else,可以使用 卫语句 进行优化。但是在实际开发中,往往不是简单 if-else 结构,我们...
  •   复习中看到设计模式中的策略模式,于是想到了之前一项目要调出含有视频的文章,又要调出含有图片的文章,略符合使用策略模式,于是想先试用一下。 策略模式   主要是用于让子类去实现不同的算法或者操作,在...
  • 通常我们会遇到一些需要做一系列条件处理的业务逻辑,并且它们每一都需要不同的处理。为了演示,我们来看一下Calulator(计算器)类的一例子。下面是带有两数字类型参数,一操作符参数以及基于操作的数值...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 84,587
精华内容 33,834
关键字:

工厂模式替换多个if