工厂方法模式

工厂方法模式是一种创建型设计模式,在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。

意图

定义一个创建对象的接口,让其子类自己决定实例化哪个工厂类,工厂模式使其创建过程延迟到子类执行。屏蔽每一个功能类中的具体实现逻辑,让外部可以更加简单的只是知道调用即可

案例

模拟积分兑换中的发放多种类型商品,有三种商品类型:

商品类型接口
实物商品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("该商品类型不支持");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YUMguyRB-1662287577336)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220904183247973.png)]

优点

  • 避免创建者与具体产品逻辑耦合、满足单一职责,每一个业务逻辑实现都再所属自己的类中完成、满足开闭原则,无需更改调用方就可以在程序中引入新的产品类型。

缺点

如果有非常多的类型,那么实现的子类会极速地扩张,因此也需要结合其他模式进行优化

借鉴

  • 《重学Java设计模式》-小傅哥
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

壹氿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值