springboot 下策略模式的简单使用

1.灵魂三问

  • 接手前人(已跑路)项目快乐否?
  • 前人项目不写注释懵逼否?
  • 一个方法中一堆if/else,且业务判断条件用简单数字(或英文字母),不带注释,想打人否?

????所以,对于上述三个问题,我写了此随笔,然而————然并卵

????这篇文章并不能让你不接手前人项目,并不能让你看懂没有注释的业务代码,也并不能让你以后不碰到if/else轰击波,但是——系尬系

????鲁迅先生曾倡导过,如果你觉得政府腐败,那么你就应该努力考取公务员从政,去内部解决腐败;如果你觉得你的家乡建设不够美丽,那么你应该去建设他;如果你觉得人民素质不够高,那么你应该提高自身素质,以身作则;如果你觉得这功能完全是业务无理取闹,产品瞎接,那么你应该——好吧,业务爸爸一切都好

????瞎扯了半天,下面进入正题:

????很多情况下,都没有一次到位得产品,也通常没有一次到位的业务需求,所以在后期的功能扩展中,很可能会造成不停的对原代码加入if/else分支判断,来满足新的业务需求,然而这对于后接手的程序员来说,在一堆if/else,几百行代码中去快速理解逻辑,并加入扩展,无疑是件很蛋疼的事(好吧,其实我的真实原因是:看起来有点丑),所以,如何改造自己的if/else代码,让其看的不显臃肿,直观简洁,我百度了一下,简单写了份在springboot环境下,利用策略模式改造代码的随笔,作为新知识的get体会!(好吧,策略模式其实很常见)

2.什么是策略模式

????策略模式(Strategy Pattern):一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

????运行时随时更改,有没有想到spring的自动注入?灵活,易扩展这也是其特点之一。有没有具体的实现步骤呢?有的!

3.简单实现步骤

简单的一个需求
  1. 首先,先假想一个简单的业务——新需求上,这个功能暂时有三个分支判断,三个分支对应不同的执行逻辑:

    • 1——孙悟空逻辑
    • 2——二师兄逻辑
    • 3——唐僧逻辑

????那么,首先,我们当然可以用if/elseswitch,来做分支判断解决,好的解决,项目上线,后期扩展——

  • 业务A有发话了,我觉得应该有4——沙师弟逻辑,对吧,是这样吧!好,我再加一个if,没问题的!
  • 业务B突然有话发话了,我觉得应该有5——三只眼逻辑,对吧,不能没有二郎神啊!好,我再加一个if,ojbk
  • 业务C突然有想法了,咋不能忘了6——小白马吧,对吧,这么辛苦!嗯~~~,可以,应该可以快速实现!
  • 业务D又来了,我觉得那白骨精挺漂亮的,是吧?你(漂亮你大爷)!!!!!!!好,还有没有漂亮的?

????所以,这个分支的类,看起来有点难受!

策略模式实现步骤

????好的话不多说,策略模式下,我们可以怎么解决这个问题呢?

  1. 首先,可以建立一个枚举类,用于存储分支判断的条件(也可以用静态变量)
public enum WestCommand {

    W_SuWuKong(1,"孙爷爷","monkeyCommand"),
    W_ZhuBaJie(2,"二师兄","pigCommand"),
    W_TangSeng(3,"和尚","monkCommand");
    private int value;

    private String descreption;

    private String beanName;

    private WestCommand(int value,String descreption,String beanName){
        this.value=value;
        this.descreption=descreption;
        this.beanName=beanName;
    }

    public int getValue(){
        return value;
    }

    public String getDescreption(){
        return descreption;
    }

    public String getBeanName(){
        return beanName;
    }
    public static WestCommand getInstance(int value) {
        for(WestCommand type : WestCommand.values()) {
            if(type.getValue() == value) {
                return type;
            }
        }
        return null;
    }

}

这个类用于存储分支判断条件,,,,,

  1. 建立策略角色接口
/**
 * @说明:
 * @类型名称:StrategyCommand
 * @创建者: Raiden
 * @创建时间: 2020/2/11 12:01
 * @修改者: Raiden
 * @修改时间: 2020/2/11 12:01
 */
public interface StrategyCommand {

    String process();
}
  1. 创建具体策略角色

/**
 * @说明:唐僧
 * @类型名称:MonkeyCommand
 * @创建者: Raiden
 * @创建时间: 2020/2/11 12:02
 * @修改者: Raiden
 * @修改时间: 2020/2/11 12:02
 */
@Service
public class MonkCommand implements StrategyCommand {
    @Override
    public String process() {
        return "和尚不曾调戏妖精了,施主还是别问了!!";
    }
}


/**
 * @说明:孙悟空
 * @类型名称:MonkeyCommand
 * @创建者: Raiden
 * @创建时间: 2020/2/11 12:02
 * @修改者: Raiden
 * @修改时间: 2020/2/11 12:02
 */
@Service
public class MonkeyCommand implements StrategyCommand {
    @Override
    public String process() {
        return "你孙爷爷叫你回家吃饭了!!";
    }
}
/**
 * @说明:二师兄
 * @类型名称:MonkeyCommand
 * @创建者: Raiden
 * @创建时间: 2020/2/11 12:02
 * @修改者: Raiden
 * @修改时间: 2020/2/11 12:02
 */
@Service
public class PigCommand implements StrategyCommand {
    @Override
    public String process() {
        return "你二师兄走位相当风骚!!";
    }
}
  1. 创建上下文,获取具体角色

这里首先需要创建一个spring的工具类,用于根据id获取bean

/**
 * @说明:
 * @类型名称:StrategeContext
 * @创建者: Raiden
 * @创建时间: 2020/2/11 14:41
 * @修改者: Raiden
 * @修改时间: 2020/2/11 14:41
 */
@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext   applicationContext) throws BeansException {
        if (SpringUtils.context==null){
            SpringUtils.context=applicationContext;
            System.out.println("初始化容器成功------------");
        }
    }
    //获取context
    public static ApplicationContext getContext(){

        return SpringUtils.context;
    }

    //通过名称获取bean
    public static Object getBean(String beanName){

        return getContext().getBean(beanName);

    }

    /**
     * 通过类型获取bean
     * @param tClass
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> tClass){

        return getContext().getBean(tClass);
    }

    public static <T> T getBean(String beanName,Class<T> classType){

        return getContext().getBean(beanName,classType);

    }

}

然后,创建上下文

/**
 * @说明:
 * @类型名称:StrategyContext
 * @创建者: Raiden
 * @创建时间: 2020/2/11 15:05
 * @修改者: Raiden
 * @修改时间: 2020/2/11 15:05
 */
public class StrategyContext {

    /**
     * 获取对应的command实现类
     * @param value
     * @param classType
     * @param <T>
     * @return
     */
    public static <T> T getStrategyBean(Integer value,Class<T> classType){
        return SpringUtils.getBean(
                WestCommand.getInstance(value).getBeanName(),classType);

    }

}

在这里,一切准备工作基本算是完成了,下面,我们来看看效果

这里我是利用的springboot+springcloud创建了一个接口:

相应的控制层:

/**
 * @说明:
 * @类型名称:StrategyCrtl
 * @创建者: Raiden
 * @创建时间: 2020/2/11 11:58
 * @修改者: Raiden
 * @修改时间: 2020/2/11 11:58
 */
@RestController
@RequestMapping("/strategy")
public class StrategyCrtl {

    @GetMapping("/{number}")
    public ResponseEntity<String> getMessage(@PathVariable Integer number){

        StrategyCommand bean = StrategyContext.getStrategyBean(number, StrategyCommand.class);

        return ResponseEntity.ok(bean.process());
    }
}

业务逻辑干掉了if/else,启动服务:

我们看一看看效果:1——孙悟空逻辑

2——二师兄逻辑

3——和尚逻辑

至于后来万一需要漂亮的白骨精,那么怎么做相信不用我多说,这看起来确实比if/else美观了不少,有人说差不多,那是因为业务爸爸层就只跟你说了一句话,万一有几百句呢?

原文地址:https://www.cnblogs.com/raidencool/p/12342237.html

时间: 2024-11-05 20:32:11

springboot 下策略模式的简单使用的相关文章

设计模式笔记——策略模式VS简单工厂模式

策略模式VS简单工厂模式   策略模式(Strategy)它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户. 1.组成 -抽象策略角色: 策略类,通常由一个接口或者抽象类实现. -具体策略角色:包装了相关的算法和行为. -环境角色:持有一个策略类的引用,最终给客户端调用. 2.应用场景 - 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为. -需要在不同情况下使用不同的策略(算法),或者策略还可能在未来

设计模式之策略模式&amp;amp;简单工厂模式

学习设计模式已经有非常长一段时间了,事实上先前已经敲过一遍了.可是老认为没有学到什么,认识也不够深刻.如今趁着重构机房,再又一次来过,也不晚. 事实上在敲了机房之后,看看模式,事实上,曾经非常难理解.非常难看懂的代码一眼就能够看懂了,趁着有点感觉了.早点收获吧. 简单工厂模式: 简单地说简单工厂模式:非常easy变化的地方,就能够用到简单工厂模式. 实例: 举个样例:我们在逛商场时.正好商场促销,各种优惠活动:有满300返100 ,有打8折的.抽奖等等吧. 促销来讲,各种优惠活动事实上就是变化.

策略模式和简单工厂

策略算法类: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace StrategyDemo { abstract class Strategy { public abstract void BillInterface(); } class ConcreteStrategyA : Strategy { public override void BillInte

策略模式与简单工厂模式

1,简单工厂模式 a) 有一个抽象的接口用来表示工厂需要生产的产品共性:然后各个具体的产品类实现该抽象接口. b) 工厂只需要持有产品的抽象接口,工厂接收一个 TYPE 参数来决定生产何种产品. c) 对于客户而言,当他需要某种类型的产品时,只需要获得工厂对象,然后将产品的 TYPE参数传递给工厂,由工厂创建他所需要的产品. 2,策略模式 策略,本质上是一种算法.当客户需要处理某件事情时,由于所处的环境不同,他可以采取不同的方式(策略)去处理.因此,客户关注的是如何方便得获取所需的策略. a)

java笔记--策略模式和简单工厂模式

策略模式: --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3884781.html "谢谢-- 为什么使用:策略模式主要用于有很多不同的方式来解决同一个问题的情景.如:文件的保存:可保存成txt,也可保存成xml.另外压缩文件.商场的促销策略等是类似的 如何使用:需要定义一个接口或者抽象类来表示各种策略的抽象,由于在选择适当的策略上有些不方便,需要不断地判断需要的类型,因此需要用简单工厂方法来实现判断过程 例子: 用策略模式实现图

策略模式结合简单工厂模式

概述 策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少各种算法类与使用算法类之间的耦合. 场景 超市收营员收钱,有打几折.满多少返现.正常收费等活动来最终算出客户应该付多少现金. 1.现金收款超类 package com.gzy.designpattern.strategyandfactory; /* * @program: mybatis-plus * @description: 现金收款超类 * @aut

策略模式+单例模式+简单工厂模式:推送服务

一.功能: 实现  获取数据  —>根据用户订阅清单进行推送 —> 这里的推送方式:QQ.Email.App.插件等等 用户可多选推送方式. 二.实现 1.推送方式—枚举(位运算): [Flags] public enum PushType { QQ = 0, Email = 2 } 2.策略模式:抽象推送策略 public interface IPush { bool Push(object data); } 3.QQ推送+Email推送 QQ推送:单例模式—静态创建QQ推送服务,线程安全.

策略模式与简单工厂模式的结合使用

Java设计模式中的策略模式(Strategy Patten)定义了一组算法,将每个算法都封装起来,并且可使它们之间可以相互替换,在客户端调用它们时可以互不影响. 策略模式主要由三个角色组成 1.抽象策略角色:通常是一个接口或抽象类实现,我们的具体策略类就是继承或实现这个抽象角色. 2.具体策略角色:我们在这些类中写策略和算法,继承或实现抽象策略角色. 3.环境角色:环境角色中拥有一个抽象策略角色的引用,供客户端调用,该角色把客户端跟策略类的实现分离. 从上面的三个策略模式的角色中,我们就大概可

策略模式和简单工厂(四)

策略模式由前端触发决定使用某一组算法或逻辑,每一组算法或逻辑不相同,互相不干扰.最后交由一个上下文具体去执行,并可以增加一定公有逻辑. 比如某电商平台搞活动: 普通会员:满100减10块 白银会员:满100减15块  送积分 黄金会员:满100减18块  送积分  参与抽奖 钻石会员:满100减20块  送积分  参与抽奖  免费送货 由会员级别决定执行哪一个活动,建一个枚举: public enum MemberLevel {     /// <summary>     /// 普通会员