当前位置: 首页 > 科技观察

摆脱ifelse!尝试这三种设计模式,轻松优化您的代码!

时间:2023-03-16 13:03:33 科技观察

前言在原有代码的基础上,如何通过设计模式一步步优化代码?在日常工作中,我们使用最多的设计模式是策略模式、工厂模式和模板方法模式。优化前伪代码的流程策略模式如何应用,工厂设计模式如何应用,模板方法模式如何应用。唠叨几句1.先看一下优化前的伪代码流程。优化前,原代码的大体逻辑。代码如下:classParameter{intpageSize;intpageNo;int请求号;//其他参数。}//逻辑处理,是否打客户群booleanisMarketHit(Parameterdto){//如果是企业客户群类型if(dto.type=='enterprise'){//没有请求关闭开关if(isEnterpriseSwitchClose){返回false;}//如果只请求一条记录if(dto.reqNum==1){//调用大数据查询接口returnsingleRemoteEOIinvoke(dto);//如果请求多条记录}elseif(dto.reqNum>1){//调用大数据批处理接口returnbatchRemoteEOIinvoke(dto);}//如果是营销型}elseif(dto.type=='market_list'){//不请求关闭if(isMarketListSwitchClose){returnfalse;}//如果只请求一条记录if(dto.reqNum==1){//调用营销查询接口returnsingleRemoteMarketinvoke(dto);//如果请求多条记录}elseif(dto.reqNum>1){//调用营销批量接口returnbatchRemoteMarketinvoke(dto);}}}这段代码可能存在什么问题?如果if分支多了,代码就会变得臃肿。如果需要接入新的类型,只能修改源代码。说的专业一点,就是上面的代码,违反了面向对象的开闭原则和单一原则。开闭原则:(对扩展开放,对修改关闭),增加或删除某个逻辑需要修改原有代码单一原则:(规定一个类应该只有一个改变的原因),修改任意的分支逻辑代码当前类需要修改。2、策略模式如何应用?大家还记得吗,如果代码中有多个if...else等条件分支,并且每个条件分支都可以封装起来,我们就可以使用策略模式来优化。回想一下,什么是策略模式?策略模式定义了一族算法,并将它们分别封装起来,使它们可以相互替换。此模式使算法更改独立于使用该算法的客户端。这个策略模式的定义是不是有点抽象?打个通俗易懂的比方:假设你在和不同性格类型的女孩约会,你需要使用不同的策略。有的适合看电影,有的适合吃零食,有的适合逛街。.目的当然是为了博取小姐的芳心。看电影、吃零食、逛街是不同的策略。Strategy模式将每一种算法封装到一个不同的独立类中,为一组算法实现一个通用的接口,这样它们就可以相互替换。我们一般如何定义策略模式?一个接口或抽象类有两个方法(一个方法匹配类型,一个可替换逻辑实现方法)区分不同策略的实现(即不同策略的实现类)。因此,对于原来的伪代码流程,我们可以定义企业客户群类型的策略实现类,营销类型的策略实现类。这两个策略实现类都实现了两个方法。一种方法是匹配类型,就是返回原代码if...else条件判断的类型;另一种方法是if...else条件的实现内容。代码如下://一个接口interfaceIGroupLabelStrategyService{//这个方法对应策略实现类的具体实现booleanprocessBiz(Parameterdto);//该方法为策略类的类型,对应```if...else```条件判断的类型StringgetType();}//企业客户群类型策略实现类EnterpriseGroupLablelStrategyServiceImplimplementsIGroupLabelStrategyService{//在企业客户组类型对应的条件分支中执行booleanprocessBiz(Parameterdto){//关闭Norequestif(isEnterpriseSwitchClose){returnfalse;}//如果只有一条记录请求if(dto.reqNum==1){//调用大数据查询接口returnsingleRemoteEOIinvoke(dto);//如果请求多条记录}elseif(dto.reqNum>1){//调用远程大数据批量接口returnbatchRemoteEOIinvoke(dto);}}//对应的企业类型StringgetType(){return"enterprise";}}//营销类型策略实现类MarketListGroupLablelStrategyServiceImplimplementsIGroupLabelStrategyService{//营销类型对应的条件分支中的实现booleanprocessBiz(Parameterdto){//无请求关闭开关if(isMarketListSwitchClose){returnfa是;}//如果只有一条请求记录if(dto.reqNum==1){//调用营销查询接口returnsingleRemoteMarketinvoke(dto);//如果请求多条记录}elseif(dto.reqNum>1){//调用营销批量接口returnbatchRemoteMarketinvoke(dto);}}StringgetType(){返回“市场列表”;}}3。如何使用工厂设计模式现在每个策略都已经实现了,不同策略的实现类是如何交给spring管理的呢?我们可以实现ApplicationContextAware接口,将策略的实现类注入到一个map中,然后根据请求者不同的策略请求类型实现不同的调用。其实和工厂模式的思路差不多。代码如下:@ComponentpublicclassGroupLabelStrategyServiceFactoryimplementsApplicationContextAware{//存放对应的类型和实现类privateMapmap=newConcurrentHashMap<>();//将策略实现类注入映射@OverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext)throwsBeansException{MaptempMap=applicationContext.getBeansOfType(IGroupLabelStrategyService.class);tmepMap.values().forEach(strategyService->map.put(strategyService.getType(),strategyService));}//工厂方法publicbooleanprocessBiz(ParamDTOdto){//根据不同的类型,得到不同的实现类IGroupLabelStrategyServicegroupLabelStrategyService=map.get(dto.getType());if(batchGroupLabelJudgeService!=null){returngroupLabelStrategyService.processBiz(dto);}返回假;}}有了策略模式+工厂方法模式,我们的伪代码过程就简化成了这样:classParameter{intpageSize;整页e否;int请求号;//其他参数}booleanisMarketHit(Parameterdto){//直接调用工厂类即可,其他逻辑处理已经在策略实现类中了。returngroupLabelStrategyServiceFactory.processBiz(dto);}4、模板方法模式是如何应用的?小伙伴们,仔细回头观察一下原来的伪代码流程,会发现一个通用的代码流程,就是先切换控件,然后根据请求的数量来决定是使用单次调用还是批量调用.这允许使用模板方法进一步优化。所谓模板方法模式,其实就是:在一个操作中定义一个算法的骨架过程,把一些步骤延迟给子类,让子类可以在不改变算法结构的情况下,重新定义算法的一些具体步骤。它的核心思想是:定义一个操作的一系列步骤,对于一些暂时不能确定的步骤,交给子类去实现,这样不同的子类就可以定义不同的步骤。为了更容易理解,我打个比方:追女朋友要先“牵手”,再“抱”,再“亲”,再“拍……额……手”。不管你是左手拿还是右手拿,但整个过程都设定了一个流程模板,你照着模板走就可以了。模板方法使用起来比较简单:一个抽象类,定义骨架过程确定的公共方法步骤(将抽象方法放在一起),将不确定的步骤放在抽象类中(去除抽象方法标记),实现去分化的子类。我们只需要将开关控制接口、单次远程调用、批量远程调用这些常用的流程定义成模板抽象类即可。代码如下:publicabstractAbstractGroupLabelJudgeTemplateimplementsIGroupLabelStrategyService{//模板骨架publicbooleanprocessBiz(Parameterdto){if(isSwitchClose){returnfalse;}if(dto.reqNum==1){返回singleRemote(dto);}elseif(dto.reqNum>1){返回batchRemote(dto);}}//开关由子类abstractbooleanisSwitchClose()控制;//单个远程调用,由子类控制astractbooleansingleRemote(dto);//batchremote调用由子类astractbooleanbatchRemote(dto);}不同的策略子类可以自己控制开关,控制不同接口的调用。EnterpriseGroupLablelStrategyServiceImplextendsAbstractGroupLabelJudgeTemplate{booleanisSwitchClose(){//企业客户群切换}booleansingleRemote(ParamDTOdto){//企业客户群单调用returnsingleRemoteEOIinvoke(dto);}booleanbatchRemote(ParamDTOdto){//企业客户群批量调用returnbatchRemoteEOIinvoke(dto);}}MarketListGroupLablelStrategyServiceImplextendsAbstractGroupLabelJudgeTemplate{booleanisSwitchClose(){//营销客群切换}booleansingleRemote(ParamDTOdto){//营销客群单调用返回singleRemoteMarketinvoke}bolean(bolean;(ParamDTOdto){//营销客群callsreturnbatchRemoteMarketinvoke(dto);}}5.策略模式、工厂模式、模板方法模式这三种设计模式是日常开发中最常用的,本文也讲解了我是如何从原始代码中提取设计模式的,以及你可以将它应用到你自己的工作中。