一、工厂模式
工厂模式又叫做工厂方法模式,是一种创建型设计模式,一般是在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。
1.1 工厂模式介绍
工厂模式是Java 中比较常见的一种设计模式,实现方法是定义一个统一创建对象的接口,让其子类自己决定去实例化那个工厂类,解决不同条件下创建不同实例的问题。工厂方法模式在实际使用时会和其他的设计模式一起结合,而不是单独使用。比如在Lottery 项目中奖品的发放就是工厂+模板+策略模式。
1.2 工厂模式实现
举个例子,比如要实现不同奖品的发放业务,有优惠券、实体商品和会员电子卡这些奖品,那么我们可以定义这三种类型奖品的接口:
从上表可以看出,不同的奖品有不同的返回类型需求,那么我们该如何处理这些数据,并对应返回呢?常规思路可以想到通过统一的入参AwardReq,出参AwardRes,外加上一个PrizeController来具体实现这些奖品的数据处理任务:
AwardReqAwardResPrizeController
但是这样势必会造成PrizeController这个类中逻辑判断过多,后期如果要继续扩展奖品类型,是非常困难和麻烦的。比如可以看看PrizeController中的代码:
public class PrizeController { private Logger logger = LoggerFactory.getLogger(PrizeController.class); public AwardRes AwardToUser(AwardReq awardReq) { String reqJson = JSON.toJSONString(awardReq); AwardRes awardRes = null; try { logger.info("奖品发放开始{}。 awardReq:{}", awardReq.getuId(), reqJson); if (awardReq.getAwardType() == 1) { CouponService couponService = new CouponService(); CouponResult couponResult = couponService.sendCoupon(awardReq.getuId(), awardReq.getAwardNumber(), awardReq.getBizId()); if ("0000".equals(couponResult.getCode())) { awardRes = new AwardRes(0000, "发放成功"); } else { awardRes = new AwardRes(0001, "发送失败"); } } else if (awardReq.getAwardType() == 2) { GoodsService goodsService = new GoodsService(); DeliverReq deliverReq = new DeliverReq(); deliverReq.setUserName(queryUserName(awardReq.getuId())); deliverReq.setUserPhone(queryUserPhoneNumber(awardReq.getuId())); deliverReq.setSku(awardReq.getAwardNumber()); deliverReq.setOrderId(awardReq.getBizId()); deliverReq.setConsigneeUserName(awardReq.getExtMap().get("consigneeUserName")); deliverReq.setConsigneeUserPhone(awardReq.getExtMap().get("consigneeUserPhone")); deliverReq.setConsigneeUserAddress(awardReq.getExtMap().get("consigneeUserAddress")); Boolean isSuccess = goodsService.deliverGoods(deliverReq); if (isSuccess) { awardRes = new AwardRes(0000, "发放成功"); } else { awardRes = new AwardRes(0001, "发送失败"); } } else { IQiYiCardService iQiYiCardService = new IQiYiCardService(); iQiYiCardService.grantToken(queryUserPhoneNumber(awardReq.getuId()), awardReq.getAwardNumber()); awardRes = new AwardRes(0000, "发送成功"); } logger.info("奖品发放完成{}。", awardReq.getuId()); } catch (Exception e) { logger.error("奖品发放失败{}。req:{}", awardReq.getuId(), reqJson, e); awardRes = new AwardRes(0001, e.getMessage()); } return awardRes; }
在PrizeController的类中,我们发现使用了很多简单的if-else判断。而且整个代码看起来很长,对于后