欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

还在用if else?策略模式了解一下!

程序员文章站 2022-05-29 09:14:12
在公司负责的就是订单取消业务,老系统中各种类型订单取消都是通过if else 判断不同的订单类型进行不同的逻辑。在经历老系统的折磨和产品需求的不断变更,决定进行一次大的重构:消灭 if else。 接下来就向大家介绍下是如何消灭 if else。 1. if else模式 若干个月再来看就是这样的感 ......

在公司负责的就是订单取消业务,老系统中各种类型订单取消都是通过if else 判断不同的订单类型进行不同的逻辑。在经历老系统的折磨和产品需求的不断变更,决定进行一次大的重构:消灭 if else。

接下来就向大家介绍下是如何消灭 if else。

1. if else模式

@service
public class cancelorderservice {

    public void process(orderdto orderdto) {
        int servicetype = orderdto.getservicetype();
        if (1 == servicetype) {
            system.out.println("取消即时订单");
        } else if (2 == servicetype) {
            system.out.println("取消预约订单");
        } else if (3 == servicetype) {
            system.out.println("取消拼车订单");
        }
    }
}

若干个月再来看就是这样的感觉
还在用if else?策略模式了解一下!

2. 策略模式

2.1 策略模式实现的service

@service
public class cancelorderstrategyservice {

    @autowired
    private strategycontext context;

    public void process(orderdto orderdto) {
        ordertypeenum ordertypeenum = ordertypeenum.getbycode(orderdto.getservicetype());
        abstractstrategy strategy = context.getstrategy(ordertypeenum);
        strategy.process(orderdto);
    }
}

简洁的有点过分了是不是!!!

2.2 各种类型策略实现及抽象策略类

下面选取了即时订单和预约订单的策略.

@service
@ordertypeannotation(ordertype = ordertypeenum.instant)
public class instantorderstrategy extends abstractstrategy {
    @override
    public void process(orderdto orderdto) {
        system.out.println("取消即时订单");
    }
}
@service
@ordertypeannotation(ordertype = ordertypeenum.booking)
public class bookingorderstrategy extends abstractstrategy {
    @override
    public void process(orderdto orderdto) {
        system.out.println("取消预约订单");
    }
}
public abstract class abstractstrategy {
    abstract public void process(orderdto orderdto);
}

2.3 策略类型注解

每个策略中增加了注解ordertypeannotation,以标注适用于不同类型的策略内容.

@target({elementtype.type})
@retention(retentionpolicy.runtime)
@documented
@inherited
public @interface ordertypeannotation {
    ordertypeenum ordertype();
}

2.4 策略处理器类strategyprocessor和策略上下文strategycontext

其中最为核心的为strategyprocessor 策略处理器类和strategycontext 策略上下文,

@component
public class strategyprocessor implements beanfactorypostprocessor {

    private static final string strategy_package = "com.lujiahao.strategy";

    @override
    public void postprocessbeanfactory(configurablelistablebeanfactory configurablelistablebeanfactory) throws beansexception {
        map<ordertypeenum, class> handlermap = maps.newhashmapwithexpectedsize(3);
        classscanner.scan(strategy_package, ordertypeannotation.class).foreach(clazz -> {
            ordertypeenum type = clazz.getannotation(ordertypeannotation.class).ordertype();
            handlermap.put(type, clazz);
        });

        strategycontext context = new strategycontext(handlermap);
        configurablelistablebeanfactory.registersingleton(strategycontext.class.getname(), context);
    }
}
public class strategycontext {
    private map<ordertypeenum, class> strategymap;

    public strategycontext(map<ordertypeenum, class> strategymap) {
        this.strategymap = strategymap;
    }

    public abstractstrategy getstrategy(ordertypeenum ordertypeenum) {
        if (ordertypeenum == null) {
            throw new illegalargumentexception("not fond enum");
        }

        if (collectionutils.isempty(strategymap)) {
            throw new illegalargumentexception("strategy map is empty,please check you strategy package path");
        }

        class clazz = strategymap.get(ordertypeenum);
        if (clazz == null) {
            throw new illegalargumentexception("not fond strategy for type:" + ordertypeenum.getcode());
        }

        return (abstractstrategy) springbeanutils.getbean(clazz);
    }
}
  • 首先会扫描指定包中标有@ordertypeannotation的类
  • 将符合类的对应的枚举值作为key,对应的类作为value,保存在策略map中
  • 初始化strategycontext,并注册到spring容器中,同时将策略map传入其中

我们使用了枚举作为map中的key,相信大家很少有人这样操作过,不过可以放心操作.通过下面两篇文章解答大家的疑问.

3. 总结

策略模式极大的减少if else等模板代码,在提升代码可读性的同时,也大大增加代码的灵活性,添加新的策略即可以满足业务需求.
本人在我司业务中对策略模式的应用得到了很好的验证,从此再也不用担心产品改需求.
用策略模式一时爽,一直用一直爽