设计模式-创建者模式-工厂方法模式
工厂方法模式#
案例:模拟发放奖品
三种奖品:优惠券,实物商品,爱奇艺兑换卡
未重构前的结构:
其中针对不同的奖品,会有不同逻辑的service方法,每个service方法的入参和返回值都不一样
-
模拟实物商品服务(返回是否发放成功的标志)
public class GoodsService { public Boolean deliverGoods(DeliverReq req) { System.out.println("模拟发货实物商品一个:" + JSON.toJSONString(req)); return true; } }
-
模拟优惠券服务(返回针对优惠券的返回结果:code,info)
public class CouponService { public CouponResult sendCoupon(String uId, String couponNumber, String uuid) { System.out.println("模拟发放优惠券一张:" + uId + "," + couponNumber + "," + uuid); return new CouponResult("0000", "发放成功"); } }
-
模拟爱奇艺会员卡服务(只输出结果,无返回值)
public void grantToken(String bindMobileNumber, String cardId) { System.out.println("模拟发放爱奇艺会员卡一张:" + bindMobileNumber + "," + cardId); }
未重构前处理逻辑的代码结构#
AwardReq是入参,统一奖品的信息形式
AwardRes是出参,统一发放奖品的返回结果形式
PrizeController的模拟发放奖品的代码逻辑
public class PrizeController {
private Logger logger = LoggerFactory.getLogger(PrizeController.class);
public AwardRes awardToUser(AwardReq req) {
String reqJson = JSON.toJSONString(req);
AwardRes awardRes = null;
try {
logger.info("奖品发放开始{}。req:{}", req.getuId(), reqJson);
// 按照不同类型方法商品[1优惠券、2实物商品、3第三方兑换卡(爱奇艺)]
if (req.getAwardType() == 1) {
CouponService couponService = new CouponService();
CouponResult couponResult = couponService.sendCoupon(req.getuId(), req.getAwardNumber(), req.getBizId());
if ("0000".equals(couponResult.getCode())) {
awardRes = new AwardRes("0000", "发放成功");
} else {
awardRes = new AwardRes("0001", couponResult.getInfo());
}
} 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.setConsigneeUserPhone(req.getExtMap().get("consigneeUserPhone"));
deliverReq.setConsigneeUserAddress(req.getExtMap().get("consigneeUserAddress"));
Boolean isSuccess = goodsService.deliverGoods(deliverReq);
if (isSuccess) {
awardRes = new AwardRes("0000", "发放成功");
} else {
awardRes = new AwardRes("0001", "发放失败");
}
} else if (req.getAwardType() == 3) {
String bindMobileNumber = queryUserPhoneNumber(req.getuId());
IQiYiCardService iQiYiCardService = new IQiYiCardService();
iQiYiCardService.grantToken(bindMobileNumber, req.getAwardNumber());
awardRes = new AwardRes("0000", "发放成功");
}
logger.info("奖品发放完成{}。", req.getuId());
} catch (Exception e) {
logger.error("奖品发放失败{}。req:{}", req.getuId(), reqJson, e);
awardRes = new AwardRes("0001", e.getMessage());
}
return awardRes;
}
private String queryUserName(String uId) {
return "花花";
}
private String queryUserPhoneNumber(String uId) {
return "15200101232";
}
}
通过AwardReq入参的awardType来判断发放什么奖品,然后执行对应奖品的对应的service服务方法
可以看出,如果只是通过iflese判断来执行不同的service方法,每一次增加一种奖品类型,都要在controller方法里新增一个判断并且在判断里也要重新填写新的service的方法,并且还要增加针对新奖品的service方法的逻辑
重构后的代码结构如下:
-
首先统一service接口
public interface ICommodity { void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception; }
-
然后分别针对不同的奖品来实现上述service接口,在这些实现方法里注入各自的单独的service方法,然后在实现方法里调用这些service方法
-
发放优惠券奖品:
public class CouponCommodityService implements ICommodity { private Logger logger = LoggerFactory.getLogger(CouponCommodityService.class); private CouponService couponService = new CouponService(); public void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception { CouponResult couponResult = couponService.sendCoupon(uId, commodityId, bizId); logger.info("请求参数[优惠券] => uId:{} commodityId:{} bizId:{} extMap:{}", uId, commodityId, bizId, JSON.toJSON(extMap)); logger.info("测试结果[优惠券]:{}", JSON.toJSON(couponResult)); if (!"0000".equals(couponResult.getCode())) throw new RuntimeException(couponResult.getInfo()); } }
-
发放爱奇艺兑换卡片奖品:
public class CardCommodityService implements ICommodity { private Logger logger = LoggerFactory.getLogger(CardCommodityService.class); // 模拟注入 private IQiYiCardService iQiYiCardService = new IQiYiCardService(); public void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception { String mobile = queryUserMobile(uId); iQiYiCardService.grantToken(mobile, bizId); logger.info("请求参数[爱奇艺兑换卡] => uId:{} commodityId:{} bizId:{} extMap:{}", uId, commodityId, bizId, JSON.toJSON(extMap)); logger.info("测试结果[爱奇艺兑换卡]:success"); } private String queryUserMobile(String uId) { return "15200101232"; } }
-
发放实物奖品:
public class GoodsCommodityService implements ICommodity { private Logger logger = LoggerFactory.getLogger(GoodsCommodityService.class); private GoodsService goodsService = new GoodsService(); public void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception { DeliverReq deliverReq = new DeliverReq(); deliverReq.setUserName(queryUserName(uId)); deliverReq.setUserPhone(queryUserPhoneNumber(uId)); deliverReq.setSku(commodityId); deliverReq.setOrderId(bizId); deliverReq.setConsigneeUserName(extMap.get("consigneeUserName")); deliverReq.setConsigneeUserPhone(extMap.get("consigneeUserPhone")); deliverReq.setConsigneeUserAddress(extMap.get("consigneeUserAddress")); Boolean isSuccess = goodsService.deliverGoods(deliverReq); logger.info("请求参数[优惠券] => uId:{} commodityId:{} bizId:{} extMap:{}", uId, commodityId, bizId, JSON.toJSON(extMap)); logger.info("测试结果[优惠券]:{}", isSuccess); if (!isSuccess) throw new RuntimeException("实物商品发放失败"); } private String queryUserName(String uId) { return "花花"; } private String queryUserPhoneNumber(String uId) { return "15200101232"; } }
-
创建工厂StoreFactory,在工厂里边装载上述的统一接口:Icommodity,然后根据入参的type判断返回什么具体的奖品服务实现方法
public class StoreFactory { public ICommodity getCommodityService(Integer commodityType) { if (null == commodityType) return null; if (1 == commodityType) return new CouponCommodityService(); if (2 == commodityType) return new GoodsCommodityService(); if (3 == commodityType) return new CardCommodityService(); throw new RuntimeException("不存在的商品服务类型"); } }
经过工厂方法重构之后,易于扩展,新增一个奖品类型,只需要新增一个实现Icommodity的服务方法,然后在工厂里增加一个判断返回该服务类即可,优点是: 避免创建者与具体的产品逻辑耦合 、 满足单一职责,每⼀个业务逻辑实现都在所属⾃自⼰己的类中完成 、 满⾜足开闭原则
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~