您的位置:首页 > 编程语言 > Java开发

Springboot中使用策略模式替代If-Else分支

2020-07-28 13:17 302 查看

一、项目中常用的if-else分支语句的分析:

 1、项目中我们可不可以使用if-else分支,该怎么使用才能使程序最优,维护起来更加的方便?首先项目中可以使用if-else分支,可以使程序通俗易懂。但是面对太多的分支或者逻辑稍微复杂的代码块,if-else分支不免显得优点乏力,在C++中貌似超过200个分支就会编译错误,在实际的交易系统中随着业务的增加,交易数会突破200+这个时候就会带来一些问题;其次,业务逻辑层等比较抽象的地方使用冗长的if else不好;同时,if-else代码违反了 open close原则(open to extesion & close to modification)。每一次有新的逻辑变动,都需要了解原有代码的逻辑,并在适当的地方增加分支语句。这要求程序员对编写非常完整的逻辑,维护起来也比较繁琐。

二、替代if-else分支的方法:

1、策略模式:为了更好的了解什么是策略模式,我们可以举个例子,中学时代每次考完数学,老师们在讲解试卷时候都会说这道题有很多种种解法,然后在黑板上写出第一种、第二中.........等等。其实这就是一种策略模式。在遇到一种问题有多种解法的时候,每个同学依据自身的想法或者不同的角度选择一种算法或者策略解决问题,过程不一样最终结果却是一样。为此我们再举一个例子:

                                              

我们锻炼身体时候可能有很多种方式,比如说我们可以跑步、做操、跳绳等等。不管我们使用哪一种方式,最终的目的都是一样的。我们可以将跑步、做操、跳绳看做一个个策略、方式,选取哪一种策略,取决于当天我们自己的意愿或者状态,但无论选择哪一种方式产生的结果都是一样的。

综上所述策略模式:定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换

2、为什么要是用策略模式:

策略模式的优点:

我们之前在选择不同的锻炼方式的时候,往往会使用if-else语句,也就是用户不选择A那么就选择B这样的一种情况。这种情况耦合性太高了,而且代码臃肿,有了策略模式我们就可以避免这种现象,策略模式遵循开闭原则,实现代码的解耦合。扩展新的方法时也比较方便,只需要继承策略接口就好了上面列出的这两点算是策略模式的优点了。同时也存在缺点。

策略模式的缺点:

客户端必须知道所有的策略类,并自行决定使用哪一个策略类。

策略模式会出现很多的策略类。

业务逻辑在使用这些策略类的时候,这些策略类由于继承了策略接口,所以有些数据可能用不到,但是依然初始化了。

3、实现策略模式:

策略模式把对象本身和运算规则区分开来,因此我们整个模式也分为三个部分。

环境类(Context):用来操作策略的上下文环境,也就是我们游客。

抽象策略类(Strategy):策略的抽象,出行方式的抽象。

具体策略类(ConcreteStrategy):具体的策略实现,每一种出行方式的具体实现。

接下来结合代码实现用策略模式代替if-else分支(Springboot):

第一步:定义抽象策略接口(定义公共接口)

[code]public interface commonStrategy extends ApplicationContextAware{

void commomInter(final ChannelHandlerContext ctx, final Object request);
/*我的工程是使用Netty客户端发过来的参数,
所以参数的类型是 ChannelHandlerContext和Object ,
可以根据自己的参数类型定义相应的参数类型*/
}

第二步:具体策略类,继承公共接口,重写其中的方法:

交易1:

[code]@Component("txn1") //注解名称,后面将会根据不同的交易名称调用具体的交易
public class dispatcher implements commonStrategy {

@Autowired
private Gson gson;
@Override
public void commomInter(final ChannelHandlerContext ctx, final Object request){

JSONObject jsonObject = gson.fromJson(request.toString(),new TypeToken<JSONObject>(){}.getType()); //使用Gson提取报文中的数据
String stringres = jsonObject.get("key").toString();
JSONObject jsonArray = JSONArray.fromObject(stringres );
List<Object> listOb = (List<Object> )jsonArray .toCollection(jsonArray ,Object.class);
for(int i = 0; i < listOb.size();i++){
/*
业务逻辑的循环处理
*/
}
}

public void setApplicationContext(ApplicationContext ctx) throws BeansException{

this.app = ctx;

}
}

 交易2:

[code]@Component("txn2") //注解名称,后面将会根据不同的交易名称调用具体的交易
public class dispatcher2 implements commonStrategy {

@Autowired
private Gson gson;

@Override
public void commomInter(final ChannelHandlerContext ctx, final Object request){

JSONObject jsonObject = gson.fromJson(request.toString(),new TypeToken<JSONObject>(){}.getType()); //使用Gson提取报文中的数据
String stringres = jsonObject.get("key").toString();
JSONObject jsonArray = JSONArray.fromObject(stringres );
List<Object> listOb = (List<Object> )jsonArray .toCollection(jsonArray ,Object.class);
for(int i = 0; i < listOb.size();i++){
/*
业务逻辑的循环处理
*/
}
}

public void setApplicationContext(ApplicationContext ctx) throws BeansException{

this.app = ctx;

}
}

自定义Spring处理器,将所有的策略类存储到Map集合中:

[code]@Service
public class MapContext{

//使用线程安全的ConcurrentHashMap,commonStrategy 公共接口
private final Map<String, commonStrategy > strategyMap = new ConcurrentHashMap<>();

//Autowired注解会自动将实现策略接口的 实现类注入到MAp中,key就是自定义的Bean的名称txn1,ten2
@Autowired
public MapContext(Map<String, commonStrategy > strategyMap){
this.strategyMap.clear();
strategyMap.forEach((k,v)-> this.strategyMap.put(k,v));
}
public void getResource(String txnNm, ChannelHandlerContext ctx,Object request){
strategyMap.get(txnNm).commomInter(ctx,request);
}

}

第三步:环境类实现:

[code]@SpringBootApplicatio’
public class test{

@Autowired
pivate MapContext context
public static void main(String arge){

SpringApplication.run(test.class,args);
JSONObject jsonObject = new JSONObject();
jsonObject.put("key",listOb);
jsonObject.put("txnNm","txn1");
ChannelHandlerContext ctx = new ChannelHandlerContext();
Object msg = new Object();
mapContext.getResource(jsonObject.get("txnNm").toString,ctx,msg);

}
}

第四步,运行结果,我们选择的是txn1交易:

                       

      选择txn2会调用交易2的逻辑。 

三、总结

       我们介绍了if-else分支使用的场景以及面对分支较多的情况下的弊端,策略模式的简单介绍以及策略模式的实现框架。当我们再原有基础上增加交易的时候,只需编写具体的交易的逻辑,继承公共接口,加上@Component("交易名称"),在客户端发起的时候,将发起的交易名称放入Map中,根据获取的交易名称统一调用mapContext.getResource(jsonObject.get("txnNm").toString,ctx,msg)方法,这样就不要修改公共方法,只需增加新的交易模块即可,方便扩展,问题容易定位。

以上演示是在Springboot中实现,另外成了Zookeeper+Dubbo+Netty实现的项目,我们将在以后的篇幅分别介绍各个技术在项目中的具体实现。以上内容有错误不正确的地方,还请指出,共同学习进步。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐