在上一篇《【设计模式】策略模式》中,我们讲解了策略模式的基本概念和用法。策略模式是符合“开闭原则”的典型案例,但在上一篇文章中,我们发现,如果想调用其他的策略,虽然不用修改核心业务代码,但需要修改客户端代码。我们说,将策略的选择放在功能页面,当用户选择时,向后端传入策略,从数据库字典表中获取该策略对应的类的名字,再通过反射,获得对应的策略类。但如果不修改数据库,还有没有别的方法?当然有!
使用spring注解!
我们将使用工厂+spring注解的方式实现!
1、工厂类
public class OrderIntegrateReadFactory { private final static Logger logger= LoggerFactory.getLogger(OrderIntegrateReadFactory.class); private Map<String,IVendeeContextStrategy> vendeeContextStrategyMap=new HashMap<String, IVendeeContextStrategy>(); public Map<String, IVendeeContextStrategy> getVendeeContextStrategyMap() { return vendeeContextStrategyMap; } public void setVendeeContextStrategyMap(Map<String, IVendeeContextStrategy> vendeeContextStrategyMap) { this.vendeeContextStrategyMap = vendeeContextStrategyMap; } public boolean doAction(String strType, ReportDetail reportDetail, OrderDetail orderDetail){ return this.vendeeContextStrategyMap.get(strType).getTicketContext(reportDetail,orderDetail); } }
2、spring配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <!--四种策略--> <bean id="orderIntegrateReadFactory" class="com.flight.inter.otaadapter.factory.OrderIntegrateReadFactory"> <property name="vendeeContextStrategyMap"> <map> <entry key="1" value-ref="ctripContextStrategy"/> <entry key="2" value-ref="qunarContextStrategy"/> <entry key="3" value-ref="aliquaContextStrategy"/> <entry key="4" value-ref="tongChengContextStrategy"/> </map> </property> </bean> <bean id="ctripContextStrategy" class="com.flight.inter.otaadapter.manage.cloudticket.CtripContextStrategy"> <property name="huitiePiaoHao" ref="ctripHuiTieTicketNumber"/> <property name="redisManage" ref="policyRedis"/> </bean> <bean id="qunarContextStrategy" class="com.flight.inter.otaadapter.manage.cloudticket.QunarContextStrategy"> <property name="huitiePiaoHao" ref="qunarHuiTieTicketNumber"/> <property name="redisManage" ref="policyRedis"/> </bean> <bean id="aliquaContextStrategy" class="com.flight.inter.otaadapter.manage.cloudticket.AliquaContextStrategy"> <property name="huitiePiaoHao" ref="quaHuiTieTicketNumber"/> <property name="redisManage" ref="policyRedis"/> </bean> <bean id="tongChengContextStrategy" class="com.flight.inter.otaadapter.manage.cloudticket.TongChengContextStrategy"> <property name="huitiePiaoHao" ref="TongChengHuiTieTicketNumber"/> <property name="redisManage" ref="policyRedis"/> </bean> </beans>
3、接口类
public interface IVendeeContextStrategy { boolean getTicketContext(ReportDetail reportDetail, OrderDetail orderDetail); }
4、具体实现类,以QunarContextStrategy策略为例
public class QunarContextStrategy implements IVendeeContextStrategy{ private final static Logger logger= LoggerFactory.getLogger(QunarContextStrategy.class); HandleManage<TicketContext> huitiePiaoHao; RedisManager redisManage; public RedisManager getRedisManage() { return redisManage; } public void setRedisManage(RedisManager redisManage) { this.redisManage = redisManage; } public HandleManage<TicketContext> getHuitiePiaoHao() { return huitiePiaoHao; } public void setHuitiePiaoHao(HandleManage<TicketContext> huitiePiaoHao) { this.huitiePiaoHao = huitiePiaoHao; } @Override public boolean getTicketContext(ReportDetail reportDetail, OrderDetail orderDetail){ try { TicketContext ticketContextQunar = QunarTicketContext(reportDetail, orderDetail); if (ticketContextQunar != null) { TicketContext ticketContext=huitiePiaoHao.handle(ticketContextQunar); if (ticketContext.isHuitieresult()){ redisManage.add("vendee-"+ticketContext.getTtsorderno(),"true"); redisManage.expire("vendee-"+ticketContext.getTtsorderno(),600); logger.info("orderintegrate huitie success data {}",JSONObject.toJSONString(ticketContext)); return true; } } }catch (Exception e){ logger.error("orerintegrate read ticketcontext error {}",e); return false; } return false; } }
5、模拟客户端调用
public class StrategyPatternDemo{ public static void main(String[] args){ OrderIntegrateReadFactory orderIntegrateReadFactory = new OrderIntegrateReadFactory (); String type = "1"; ReportDetail reportDetail = new ReportDetail(); OrderDetail orderDetail = new OrderDetail(); reportDetail.setXXX(); orderDetail.setXXX(); ... ... Boolean boolean = orderIntegrateReadFactory.doAction(strType, reportDetail,orderDetail); } }
当需求中有新的类时,我们可以在只添加策略类,修改spring的配置文件来实现啦!
代码借鉴:
https://blog.csdn.net/zlts000/article/details/54754789