奉贤宜昌网站建设,网站多久被百度收录,去哪儿旅行app下载安装,手机制作海报一、策略模式
1.1策略模式定义
在策略模式#xff08;Strategy Pattern#xff09;中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式定义了一系列算法或策略#xff0c;并将每个算法封装在独立的类中#xff0c;使得它们可以互相…一、策略模式
1.1策略模式定义
在策略模式Strategy Pattern中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式定义了一系列算法或策略并将每个算法封装在独立的类中使得它们可以互相替换。通过使用策略模式可以在运行时根据需要选择不同的算法而不需要修改客户端代码。
在策略模式中我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
1.2 使用场景
1、如果在一个系统里面有许多类它们之间的区别仅在于它们的行为那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
2、一个系统需要动态地在几种算法中选择一种。
3、如果一个对象有很多的行为如果不用恰当的模式这些行为就只好使用多重的条件选择语句来实现。 二、工厂模式
2.1工厂模式定义
工厂模式Factory Pattern是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式它提供了一种创建对象的最佳方式。
工厂模式提供了一种将对象的实例化过程封装在工厂类中的方式。通过使用工厂模式可以将对象的创建与使用代码分离提供一种统一的接口来创建不同类型的对象。
在工厂模式中我们在创建对象时不会对客户端暴露创建逻辑并且是通过使用一个共同的接口来指向新创建的对象。
2.2 使用场景 1、日志记录器记录可能记录到本地硬盘、系统事件、远程服务器等用户可以选择记录日志到什么地方。
2、数据库访问当用户不知道最后系统采用哪一类数据库以及数据库可能有变化时。
3、设计一个连接服务器的框架需要三个协议POP3、IMAP、HTTP可以把这三个作为产品类共同实现一个接口。
注意事项作为一种创建类模式在任何需要生成复杂对象的地方都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式而简单对象特别是只需要通过 new 就可以完成创建的对象无需使用工厂模式。如果使用工厂模式就需要引入一个工厂类会增加系统的复杂度。 三、实现 需求为用户在美团上购买物品后的核销业务,根据一个周期内(周期为时间,如一个月,一周等)不同核销完成后的返回结果进行核销限制添加积分等,例如是否是本公司app下的会员,是否添加本公司企微,是否关注本公司公众号来进行对应操作,(后续可能会添加其他核销方式),所以该处可利用策略模式实现,而不是一长串的if..else进行功能的实现,违反了开闭原则(对扩展开放对修改封闭),
3.1 使用if...else实现功能伪代码 过多嵌套,后续扩展功能不利于维护,实现简单
public class StrategyTest {Resourceprivate TbUserDao tbUserDao;Resourceprivate TbActivityDao tbActivityDao;Resourceprivate MtCouponService mtCouponService;Testpublic Object verify (String userId,String receipt_code) {MapString,Object result new HashMap();//1. 获取用户信息TbUser tbUser tbUserDao.selectUserByUserId(userId);if (null tbUser) {return null;}// 根据receipt_code 和 skuId 查询出需要核销的类型// 2. 根据不同的核销次数进行核销限制String callBackMsg mtCouponService.getCoinByReceiptCode(receipt_code, userId, 杭州);Map callBackMap JSON.parseObject(callBackMsg, Map.class);if (200.equals(callBackMap.get(code))) {//2.1. 判断次数进行选择if(.....) {...}else if(....){...} else if(....){...} else if(....){...} }result.put(code, 505);result.put(msg, callBackMap.get(msg));return result;}
} 3.2 使用策略模式工厂模式 涉及到实际业务,服务实现直接简化为打印相应核销策略
抽象策略类接口
public interface VerificationService {String verificationName();void verify();
}
实现具体策略服务
MtCouponService 核销服务UserService 用户服务LinkedWeChatService RPC判断用户状态服务
Service
public class OfficialAccountsVerifyServiceImpl implements VerificationService{Resourceprivate UserService userService;Resourceprivate MtCouponService mtCouponService;Overridepublic String verificationName() {return VerificationEnum.OfficialAccounts.getName();}Overridepublic Object verify(String receipt_code, String userId,String cityName) {MapString, Object resultMap new HashMap();TbUser tbUser userService.selectUserByUserId(userId);if (null tbUser) {return JSON.toJSONString(new CommonView(500, 用户不存在, null));}String response HttpUtil.get(http://localhost:9088/wx/wxUserTags/isSubcribe?unionId tbUser.getThirdUserId());Map result JSON.toJavaObject(JSON.parseObject(response), Map.class);Object data result.get(data);if (true.equals(data.toString())) {return mtCouponService.getCoinByReceiptCode(receipt_code, userId ,cityName);}resultMap.put(code, 501);resultMap.put(msg, 请关注公众号后再进行核销!);return resultMap;}
} 该功能还在完善
Service
public class VipVerifyServiceImpl implements VerificationService{Resourceprivate MtCouponService mtCouponService;Overridepublic String verificationName() {return VerificationEnum.Vip.getName();}Overridepublic Object verify(String receipt_code, String userId,String cityName) {System.out.println(会员核销 );MapString, Object resultMap new HashMap();resultMap.put(code, 501);resultMap.put(msg, 请开通Vip后再进行核销!);return resultMap;}
}
Service
public class WeComGroupVerifyServiceImpl implements VerificationService{Resourceprivate LinkedWeChatService linkedWeChatService;Resourceprivate MtCouponService mtCouponService;Overridepublic String verificationName() {return VerificationEnum.WeComGroup.getName();}Overridepublic Object verify(String receipt_code, String userId,String cityName) {MapString, Object resultMap new HashMap();boolean status linkedWeChatService.existsCustomerInGroup(userId);if (status) { //入群return mtCouponService.getCoinByReceiptCode(receipt_code, userId ,cityName);}resultMap.put(code, 501);resultMap.put(msg, 请加群后再进行核销!);return resultMap;}
}
Service
public class WeComVerifyServiceImpl implements VerificationService{Resourceprivate LinkedWeChatService linkedWeChatService;Resourceprivate MtCouponService mtCouponService;Overridepublic String verificationName() {return VerificationEnum.WeCom.getName();}Overridepublic Object verify(String receipt_code, String userId,String cityName) {MapString, Object resultMap new HashMap();boolean status linkedWeChatService.existsUnionId(userId);if (status) { //添加企微return mtCouponService.getCoinByReceiptCode(receipt_code, userId ,cityName);}resultMap.put(code, 501);resultMap.put(msg, 请添加企微后再进行核销!);return resultMap;}
}
环境类
/*** 核销枚举类*/
public enum VerificationEnum {/*** 默认*/defaultVerify( defaultVerify),/*** 企微*/WeCom( WeCom),/*** 入群*/WeComGroup(WeComGroup),/*** 公众号*/OfficialAccounts( OfficialAccounts),/*** 会员*/Vip(Vip);private String name;VerificationEnum(String name) {this.name name;}public String getName() {return name;}public void setName(String name) {this.name name;}
}/*** 初始化,并获取VerificationService所有服务bean*/
Component
Slf4j
public class StrategyHandler implements InitializingBean, ApplicationContextAware {/*** 存放策略的map,可以理解为策略的注册中心*/Resourceprivate final MapString, VerificationService strategyServiceMap new ConcurrentHashMap(16);/*** spring的上下文*/private ApplicationContext applicationContext;private static final Integer DAY_BETWEEN -60;Overridepublic void afterPropertiesSet() {//初始化把所有的策略bean放进ioc,使用的时候获取MapString, VerificationService matchBeans applicationContext.getBeansOfType(VerificationService.class);//策略注入的bean做key,策略实现类做valuematchBeans.forEach((key, value) - {strategyServiceMap.put(value.verificationName(), value);
// log.info(项目启动时初始化核销策略模式为: key{},value{}, key, value);});}/**** param applicationContext spring的上下文* throws BeansException 获取bean异常*/Overridepublic void setApplicationContext(NotNull(message bean不能为空) ApplicationContext applicationContext) throws BeansException {this.applicationContext applicationContext;}/*** 通过key获取对应的策略实现** param verifyNum 根据次数选择对应核销方式 (String类型或者整形都行,保持和策略接口一致就行)* return VerificationService 具体的核销服务*/public Object getStrategy(int verifyNum, String receipt_code, String userId,String cityName) throws RuntimeException{switch (verifyNum) {case 0:case 1:log.info(使用默认核销);return strategyServiceMap.get(VerificationEnum.defaultVerify.getName()).verify(receipt_code,userId,cityName);case 2:log.info(当前核销次数为3次---WeCom);return strategyServiceMap.get(VerificationEnum.WeCom.getName()).verify(receipt_code,userId,cityName);case 3:log.info(当前核销次数为4次---WeComGroup);return strategyServiceMap.get(VerificationEnum.WeComGroup.getName()).verify(receipt_code,userId,cityName);case 4:log.info(当前核销次数为5次---OfficialAccounts);return strategyServiceMap.get(VerificationEnum.OfficialAccounts.getName()).verify(receipt_code,userId,cityName);
// case 5:
// strategyServiceMap.get(VerificationEnum.Vip.getName()).verify(userId);
// break;default:log.info(当前核销次数为6次及以上---禁止核销);break;}CouponResult result new CouponResult();result.setCode(501);result.setMsg(当前验券次数超过6次,该周期禁止核销);result.setValue(0);return JSON.toJSONString(result);} *初始化项目时直接注册服务,方便调用 调用方便,易扩展,但是实现过程较繁琐, PostMapping(value /verify)SignCtrlResponseBodyApiResponses(value {ApiResponse(code 400, message 验券未通过),ApiResponse(code 500, message 用户不存在),ApiResponse(code 501, message 禁止核验),ApiResponse(code 501, message 券码不存在),ApiResponse(code 1003, message 库存不足),ApiResponse(code 1006, message 券码输入错误),ApiResponse(code 1008, message 券码已使用过),ApiResponse(code 1009, message 券码已失效),ApiResponse(code 1010, message 退券中的消费券),ApiResponse(code 1011, message 已退券的消费券),ApiResponse(code 1012, message 此团购券不可在本店消费请确认正确分店)})public Object verify(String receipt_code,String userId,String cityName) {Map mtCoupon mongoTemplate.findOne(new Query(Criteria.where(receiptCode).is(receipt_code)),Map.class, tbopen_shop_uuid);ListTbActivity tbActivities;if (mtCoupon ! null) {Calendar instance Calendar.getInstance();instance.setTime(new Date());instance.add(Calendar.DATE, DAY_BETWEEN);tbActivities activityDao.selectMTOrderByUserId(userId,DateUtils.getNowDate(instance.getTime()), DateUtils.formatDate(new Date()));int verify 0;if (tbActivities ! null) {Object[] receipt_codeArray tbActivities.stream().map(TbActivity::getActivitySource).toArray();ListMap verifyList mongoTemplate.find(new Query(Criteria.where(receiptCode).in(receipt_codeArray).and(skuId).is(mtCoupon.get(skuId))),Map.class, tbopen_shop_uuid);verify verifyList.size();}return strategyHandler.getStrategy(verify, receipt_code, userId, cityName);}HashMapObject, Object map new HashMap();map.put(msg, 券码不存在);return JSON.toJSONString(new CommonView(502,成功, map));}
四 总结
4.1 优点
提高了代码的复用性和可维护性将算法的定义与其具体实现进行解耦。可以在运行时动态替换算法提高了程序的灵活性。符合开闭原则新增算法无需修改现有代码。
4.2 缺点
客户端需要知道所有的策略类并根据具体场景选择合适的策略增加了客户端的复杂度。如果策略类较多会导致类的数量增多增加系统的复杂度。
4.3 适用场景
当一个系统中存在多个类只有它们的行为或算法不同时。当一个类定义了多种行为而这些行为在这个类的操作中以多个条件语句的形式出现可以将相关的条件分支移入它们各自的策略类中以替换这些条件语句。当系统需要动态地在几种算法中选择一种时如根据不同的配置、用户选择或者环境条件等。