工厂方法模式是一种创建型设计模式,在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。
意图
定义一个创建对象的接口,让其子类自己决定实例化哪个工厂类,工厂模式使其创建过程延迟到子类执行。屏蔽每一个功能类中的具体实现逻辑,让外部可以更加简单的只是知道调用即可。
案例
模拟积分兑换中的发放多种类型商品,有三种商品类型:
商品类型 | 接口 |
---|---|
实物商品 | Boolean deliverGoods(deliverReq req); |
优惠券 | CouponResult sendCoupon(String uId,String couponNumber,String uuid); |
爱奇艺会员兑换卡 | void grantToken(String bindMobileNumber,String cardId); |
- 三个接口返回类型不同
- 入参不同,因为每种商品需要的东西不同
- 可能后续会新增其他的商品类型
实现
普通实现(源代码)
public AwardResp awardToUser(AwardReq req) {
String reqJson = JSONObject.toJSONString(req);
log.info("奖品发放开始{}. req:{}", req.getUId(), reqJson);
AwardResp resp = null;
try {
//按照不同类型方法商品[1.优惠券 2.实物商品 3.爱奇艺会员兑换卡]
if (req.getAwardType() == 1) {
CouponService couponService = new CouponService();
CouponResult couponResult = couponService.sendCoupon(req.getUId(), req.getAwardNumber(), req.getBizId());
if ("200".equals(couponResult.getCode())) {
resp = new AwardResp("200", "发放成功");
} else {
resp = new AwardResp("500", couponResult.getMessage());
}
} else if (req.getAwardType() == 2) {
GoodsService goodsService = new GoodsService();
DeliverReq deliverReq = new DeliverReq();
deliverReq.setUserName(queryUserName(req.getUId()));
deliverReq.setUserPhone(queryUserPhoneNumber(req.getUId()));
deliverReq.setSku(req.getAwardNumber());
deliverReq.setOrderId(req.getBizId());
deliverReq.setConsigneeUserName(req.getExtMap().get("consigneeUserName"));
deliverReq.setConsigneeUserAddress(req.getExtMap().get("consigneeUserAddress"));
deliverReq.setConsigneeUserPhone(req.getExtMap().get("consigneeUserPhone"));
Boolean sendResult = goodsService.deliverGoods(deliverReq);
if (sendResult) {
resp = new AwardResp("200", "发放成功");
} else {
resp = new AwardResp("500", "发放失败");
}
} else if (req.getAwardType() == 3) {
IQiYiCardService iQiYiCardService = new IQiYiCardService();
iQiYiCardService.grantToken(queryUserPhoneNumber(req.getUId()), req.getAwardNumber());
resp = new AwardResp("200", "发放成功");
}
log.info("奖品发放完成:" + req.getUId());
} catch (Exception e) {
log.info("奖品发放异常 ,用户{},req:{}", req.getUId(), reqJson, e);
resp = new AwardResp("500", e.getMessage());
}
return resp;
}
设计模式实现
/**
* Description:发奖接口,无论是什么商品类型都需要实现这个接口,统一出入参
*/
public interface ICommodity {
/**
* @param uId 用户ID
* @param commodityId 商品ID
* @param bizId 业务ID
* @param extParam 扩展字段
*/
void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extParam) throws Exception;
}
/**
* Description:商店工厂
*
* @author li.hongjian
* @email lhj502819@163.com
* @since 2022/9/4 11:47
*/
public class StoreFactory {
public ICommodity getCommodityService(Integer commodityType) {
if (null == commodityType) {
return null;
}
switch (commodityType) {
case 1:
return new CouponCommodityService();
case 2:
return new GoodsCommodityService();
case 3:
return new IQiYiCommodityService();
}
throw new RuntimeException("该商品类型不支持");
}
}
优点
- 避免创建者与具体产品逻辑耦合、满足单一职责,每一个业务逻辑实现都再所属自己的类中完成、满足
开闭原则
,无需更改调用方就可以在程序中引入新的产品类型。
缺点
如果有非常多的类型,那么实现的子类会极速地扩张,因此也需要结合其他模式进行优化
借鉴
- 《重学Java设计模式》-小傅哥