一次代码优化实践,用了模板方法+策略+工厂方法模式

开发 前端
好久没分享工作总结啦,今天来一份代码优化总结。用模板方法+策略+工厂方法模式优化了代码,耐心点看完,应该对大家有帮助的~

[[343344]]

前言

好久没分享工作总结啦,今天来一份代码优化总结。用模板方法+策略+工厂方法模式优化了代码,耐心点看完,应该对大家有帮助的~

本文已经收录到github

https://github.com/whx123/JavaHome

优化代码前

先来了解一下类似的业务场景,简言之,就是:多个商户接入我们系统,都是走一个类似的流程通过http请求出去的。

优化前,每个公司对应一个句柄服务,伪代码如下:

  1. // 商户A处理句柄 
  2. CompanyAHandler implements RequestHandler { 
  3.    Resp hander(req){ 
  4.    //查询商户信息 
  5.    queryMerchantInfo(); 
  6.    //加签 
  7.    signature(); 
  8.    // http请求(走代理) 
  9.    httpRequestbyProxy() 
  10.    // 验签 
  11.    verify(); 
  12.    } 
  13. // 商户B处理句柄 
  14. CompanyBHandler implements RequestHandler { 
  15.    Resp hander(Rreq){ 
  16.    //查询商户信息 
  17.    queryMerchantInfo(); 
  18.    //加签 
  19.    signature(); 
  20.    // http请求(不走代理) 
  21.    httpRequestbyDirect(); 
  22.    // 验签 
  23.    verify();  
  24.    } 
  25. // 商户C处理句柄 
  26. CompanyBHandler implements RequestHandler { 
  27.    Resp hander(Rreq){ 
  28.    //查询商户信息 
  29.    queryMerchantInfo(); 
  30.    // webservice 方式调用 
  31.    requestByWebservice(); 
  32.    } 

优化代码思路

我的优化代码思路,是有「重复代码,先把它抽出来,或者公用变量,或者公用方法,伸着公用类」。所以呢,查询商户信息呀,加签呀,http请求呀先全部各抽成一个公用方法。你细心点会发现,连每个Handler处理过程都很类似的,大概都是查询商户信息+加签+http请求+验签,于是呢,可以直接把它们抽象成一个公用类呀~在这里就要引入模板方法模式咯

模板方法模式

  1. 在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。 
  2. 这种类型的设计模式属于行为型模式。 

这种类型的设计模式属于行为型模式。

既然每个Handler处理,都是类似的流程,那「定义一个抽象类,把查询商户信息,加签,http请求,验签什么的,都放到里面去,俨然一个模板一样」。然后,因为有些商户走http代理,有些又没走代理,怎么办呢? 定义「一个抽象方法,给子类实现」嘛,因为能共用就放到父类(当前的抽象类),不能共用就放到子类嘛~代码如下:

  1. abstract class AbstractCompanyCommonService implements ICompanyCommonService {  
  2.      //模板方法 
  3.      Resp handlerTempPlate(req){ 
  4.             //查询商户信息 
  5.            queryMerchantInfo(); 
  6.            // 加签 
  7.            signature(); 
  8.            //http 请求 
  9.            if(isRequestByProxy()){ 
  10.               httpProxy(); 
  11.             }else
  12.               httpDirect(); 
  13.              } 
  14.             // 验签 
  15.             verifySinature(); 
  16.      } 
  17.       // Http是否走代理 
  18.       abstract boolean isRequestByProxy(); 

子类商户A实现:

  1. CompanyAServiceImpl extends AbstractCompanyCommonService{ 
  2.     Resp hander(req){ 
  3.       return handlerTempPlate(req); 
  4.     } 
  5.     //公司A是走代理的 
  6.     boolean isRequestByProxy(){ 
  7.        return true
  8.     } 

子类商户B实现:

  1. CompanyBServiceImpl extends AbstractCompanyCommonService{ 
  2.     Resp hander(req){ 
  3.       return handlerTempPlate(req); 
  4.     } 
  5.     //公司B是不走代理的 
  6.     boolean isRequestByProxy(){ 
  7.        return false
  8.     } 

策略模式

心细的读者会发现,甚至提出疑问,「你的商户C的服务实现跟你定义的公用模板,不太一样呢」,那当然,实际开发中,不跟你定义的模板一样太常见了,需求是产品提的嘛,又不是根据你模板提的,是代码服务于需求的。好了,不多说啦,我使用了策略模式,来优化这个问题。

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

策略模式理解起来其好抽象对不对?我个人理解,其实策略模式就是定义一个方法(所谓算法),给子类自己去实现。实际上就是「定义个方法/接口,让子类自己去实现」。看代码吧:

  1. // 定义一个方法,把策略交给子类去实现。 
  2. interface ICompanyCommonService{ 
  3.   Resp hander(req); 

前面商户A和商户B还是不变,使用抽象类AbstractCompanyCommonService的模板,模板不满足商户C,商户C只能自己去实现咯,各个子类自己去实现的行为,就是策略模式的体现呢,如下:

  1. CompanyCServiceImpl extends AbstractCompanyCommonService{ 
  2.     Res hander(req){ 
  3.        //查询商户信息 
  4.        queryMerchantInfo(); 
  5.        requestByWebservice();     
  6.     } 
  7.     //随意了,你都不走模板了 
  8.     boolean isRequestByProxy(){ 
  9.        return false
  10.     } 

工厂方法模式

商户A、B、C服务怎么被管理呢,之前分别给A,B,C服务实现handler的,现在好了,都不知道怎么管理了,怎么知道调用哪个呢?别慌,解决方案是「工厂方法模式」。

  1. 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。 

工厂方法模式具体实现就是:接口定义一个枚举,每个服务实现都重新实现枚举,设置唯一标志枚举,再交给spring容器管理。看代码咯:

  1. interface ICompanyCommonService{ 
  2.   Resp hander(req); 
  3.   CompanyEnum getCompanyEnum(); 
  4.  
  5. CompanyAServiceImpl extends AbstractCompanyCommonService{ 
  6.     Resp hander(req){ 
  7.       return handlerTempPlate(req); 
  8.     } 
  9.     //公司A是走代理的 
  10.     boolean isRequestByProxy(){ 
  11.        return true
  12.     } 
  13.     CompanyEnum getCompanyEnum(){ 
  14.      return CompanyEnum.A; 
  15.     }  
  16.      
  17. CompanyBServiceImpl extends AbstractCompanyCommonService{ 
  18.     Resp hander(req){ 
  19.       return handlerTempPlate(req); 
  20.     } 
  21.     //公司B是不走代理的 
  22.     boolean isRequestByProxy(){ 
  23.        return false
  24.     } 
  25.     CompanyEnum getCompanyEnum(){ 
  26.      return CompanyEnum.B; 
  27.     }  

来来来,工厂方法模式出炉咯:

  1. @Component 
  2. public class CompanyServiceFactory implements ApplicationContextAware { 
  3.  
  4.     private static Map<CompanyEnum, ICompanyCommonService> map = new HashMap<>(); 
  5.  
  6.     @Override 
  7.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
  8.         Map<String, ICompanyCommonService> tempMap = applicationContext.getBeansOfType(ICompanyCommonService.class); 
  9.         tempMap.values().forEach(iCompanyCommonService -> 
  10.                 map.put(iCompanyCommonService.getCompanyEnum(), iCompanyCommonService)); 
  11.     } 
  12.  
  13.     public Resp handler(req) { 
  14.         return map.get(CompanyEnum.getCompanyEnum(req.getCompanyFlag()).hander(req); 
  15.     } 

最后建议

最后,不要为了使用设计模式生搬硬套,而是优化代码过程中,发现这个设计模式刚好适用,才去用的哈。附上最后的代码咯:

  1. @Service 
  2. public class CompanyHandler implements RequestHandler  { 
  3.    @Autowire 
  4.    private CompanyServiceFactory companyServiceFactory; 
  5.     
  6.    Resp hander(req){ 
  7.     return companyServiceFactory.handler(req); 
  8.   } 

本文转载自微信公众号「捡田螺的小男孩」,可以通过以下二维码关注。转载本文请联系捡田螺的小男孩公众号。

 

责任编辑:武晓燕 来源: 捡田螺的小男孩
相关推荐

2024-02-20 12:09:32

模式工厂方法接口

2010-10-09 09:25:35

Python工厂模式

2013-11-26 16:29:22

Android设计模式

2020-08-11 11:20:30

Typescript设计模式

2009-01-15 10:55:29

JavaScript设计模式抽象工厂

2023-09-11 08:30:30

Creator工厂方法

2021-03-02 20:42:20

实战策略

2023-08-05 13:31:20

工厂方法模式对象

2023-11-06 07:45:42

单据图片处理

2023-05-15 08:38:58

模板方法模式

2019-01-21 11:17:13

CPU优化定位

2023-10-27 08:34:46

PythonJava优势

2024-02-21 12:24:33

模板设计模式框架

2023-12-12 11:09:55

模板方法模式python设计模式

2012-07-11 08:51:51

设计模式

2013-11-26 17:15:13

Android设计模式

2021-07-16 23:01:03

SQL索引性能

2015-07-14 10:34:42

ViewModel代码高效

2014-03-14 10:07:09

极限编程敏捷开发

2022-08-15 08:16:56

shiroWeb认证
点赞
收藏

51CTO技术栈公众号