前言
笔者是金融行业,负责出单系统开发,出单按渠道来源划分有很多种方式,业务员页面直接录单的提交审核后会提交到审核员核保,对于一些特定渠道出单的,会直接自动审核。所以这边可能会有很多种场景,针对不同的渠道来源标识需要不同的逻辑进行处理。一般在代码中会根据If else 写很多的判断,考虑到开闭原则,拓展性等问题,这里使用了策略设计模式来处理。
业务场景:
概述
从业务场景图中可以看到,三种出单来源会有不同的逻辑处理,但是他们都是属于同一种行为,审核逻辑处理,既然都有同个特性,我们就可以抽象出一个接口,不同渠道来源对应一个逻辑实现类。这样我们就有了三个处理类,但是这三者还没有嵌入业务流程的,我们需要一个管理类来将这两者关联起来。
测试用例
编写抽象类
public interface Audit { public void execute(String data); }
页面来源处理器
public class WebAudit implements Audit { @Override public void execute(String data) { System.out.println("页面录单来源:提交上级审核"); } }
渠道A来源处理器
public class ChannelAAudit implements Audit { @Override public void execute(String data) { System.out.println("渠道A来源,自动审核通过"); } }
渠道B来源处理器
public class ChannelBAudit implements Audit { @Override public void execute(String data) { System.out.println("渠道B来源,自动审核通过"); } }
策略处理器
public class AuditContext { private Audit audit; public AuditContext(Audit audit) { this.audit=audit; } public void handle(String data){ audit.execute(data); } }
测试
public class ChannelBAudit implements Audit { @Override public void execute(String data) { System.out.println("渠道B来源,自动审核通过"); } }
这样我们就完成了策略模式的编写,但是大家应该也发现问题,就是我们需要去new对象,而且也没有根据业务来源标识来自动创建。虽然策略模式能将各个功能独立开,但是针对这次的业务场景还需要结合简单工厂模式。
结合简单工厂模式
我们改造一些策略处理器,将简单工厂模式嵌入进去。
public class AuditContext { private Audit audit; public AuditContext(String channelFlag)throws Exception { switch (channelFlag){ case "W": audit=new WebAudit(); break; case "A": audit=new ChannelAAudit(); break; case "B": audit=new ChannelBAudit(); break; } if (audit==null){ throw new RuntimeException("找不到处理器!"); } } public void handle(String data){ audit.execute(data); } }
测试
public static void main(String[] args) throws Exception { String channelFlag="A"; AuditContext auditContext = new AuditContext(channelFlag); auditContext.handle("业务数据"); }
总结
策略模式是一种定义一系列算法的方法,每个实现类逻辑分开,互相独立,可以降低耦合度。针对这次的需求有多种设计模式可以运用,因为业务场景不是特别多,而且这种可读性比较好,后面拓展的时候直接增加一个类型即可,具体还是得根据业务发展来调整,没办法一次性就变得完善。
优点
策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码转移到父类里面,从而避免重复的代码。
策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。
使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。
缺点
客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
策略模式造成很多的策略类,每个具体策略类都会产生一个新类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来减少对象的数量。