工厂模式的学习

本文通过对比未使用和使用工厂方法模式的奖品发放服务,展示了工厂方法如何降低代码耦合,提高代码可维护性。在改造后的代码中,通过创建仓库工厂并根据奖品类型动态实例化服务,实现了优惠券、实物商品和第三方兑换卡的发放,简化了原本复杂的if-else逻辑,使得新增奖品类型更加灵活。
摘要由CSDN通过智能技术生成

1.狂神版

在这里插入图片描述
简单工厂模式
在这里插入图片描述
工厂方法模式
在这里插入图片描述

2.小傅哥版本 (工厂方法模式)

爱奇艺 会员卡服务
在这里插入图片描述
优惠券 服务
在这里插入图片描述
优惠券 结果
在这里插入图片描述
实体商品 服务
在这里插入图片描述
发货 信息
在这里插入图片描述


1. 未使用工厂方法模式
在这里插入图片描述

public class AwardReq {

    private String uId;                 // 用户唯一ID
    private Integer awardType;          // 奖品类型(可以用枚举定义);1优惠券、2实物商品、3第三方兑换卡(爱奇艺)
    private String awardNumber;         // 奖品编号;sku、couponNumber、cardId
    private String bizId;  
    ... 
public class AwardRes {

    private String code; // 编码
    private String info; // 描述
    ...

/**
 * 模拟发奖服务
 */
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";
    }

}

开始测试

@Test
    public void test_awardToUser() {

        PrizeController prizeController = new PrizeController();

        System.out.println("\r\n模拟发放优惠券测试\r\n");
        // 模拟发放优惠券测试
        AwardReq req01 = new AwardReq();
        req01.setuId("10001");
        req01.setAwardType(1);
        req01.setAwardNumber("EGM1023938910232121323432");
        req01.setBizId("791098764902132");
        AwardRes awardRes01 = prizeController.awardToUser(req01);

        logger.info("请求参数:{}", JSON.toJSON(req01));
        logger.info("测试结果:{}", JSON.toJSON(awardRes01));

        System.out.println("\r\n模拟方法实物商品\r\n");
        // 模拟方法实物商品
        AwardReq req02 = new AwardReq();
        req02.setuId("10001");
        req02.setAwardType(2);
        req02.setAwardNumber("9820198721311");
        req02.setBizId("1023000020112221113");
        req02.setExtMap(new HashMap<String, String>() {{
            put("consigneeUserName", "谢飞机");
            put("consigneeUserPhone", "15200292123");
            put("consigneeUserAddress", "吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109");
        }});

        AwardRes awardRes02 = prizeController.awardToUser(req02);
        logger.info("请求参数:{}", JSON.toJSON(req02));
        logger.info("测试结果:{}", JSON.toJSON(awardRes02));

        System.out.println("\r\n第三方兑换卡(爱奇艺)\r\n");
        AwardReq req03 = new AwardReq();
        req03.setuId("10001");
        req03.setAwardType(3);
        req03.setAwardNumber("AQY1xjkUodl8LO975GdfrYUio");

        AwardRes awardRes03 = prizeController.awardToUser(req03);
        logger.info("请求参数:{}", JSON.toJSON(req03));
        logger.info("测试结果:{}", JSON.toJSON(awardRes03));

    }

输出的结果

模拟发放优惠券测试

15:07:44.841 [main] INFO  o.i.demo.design.PrizeController - 奖品发放开始10001。req:{"awardNumber":"EGM1023938910232121323432","awardType":1,"bizId":"791098764902132","uId":"10001"}
模拟发放优惠券一张:10001,EGM1023938910232121323432,791098764902132
15:07:44.848 [main] INFO  o.i.demo.design.PrizeController - 奖品发放完成1000115:07:44.850 [main] INFO  org.itstack.demo.test.ApiTest - 请求参数:{"uId":"10001","bizId":"791098764902132","awardNumber":"EGM1023938910232121323432","awardType":1}
15:07:44.852 [main] INFO  org.itstack.demo.test.ApiTest - 测试结果:{"code":"0000","info":"发放成功"}

模拟方法实物商品

15:07:44.853 [main] INFO  o.i.demo.design.PrizeController - 奖品发放开始10001。req:{"awardNumber":"9820198721311","awardType":2,"bizId":"1023000020112221113","extMap":{"consigneeUserName":"谢飞机","consigneeUserPhone":"15200292123","consigneeUserAddress":"吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109"},"uId":"10001"}
模拟发货实物商品一个:{"consigneeUserAddress":"吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109","consigneeUserName":"谢飞机","consigneeUserPhone":"15200292123","orderId":"1023000020112221113","sku":"9820198721311","userName":"花花","userPhone":"15200101232"}
15:07:44.856 [main] INFO  o.i.demo.design.PrizeController - 奖品发放完成1000115:07:44.857 [main] INFO  org.itstack.demo.test.ApiTest - 请求参数:{"extMap":{"consigneeUserName":"谢飞机","consigneeUserAddress":"吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109","consigneeUserPhone":"15200292123"},"uId":"10001","bizId":"1023000020112221113","awardNumber":"9820198721311","awardType":2}
15:07:44.857 [main] INFO  org.itstack.demo.test.ApiTest - 测试结果:{"code":"0000","info":"发放成功"}

第三方兑换卡(爱奇艺)

15:07:44.857 [main] INFO  o.i.demo.design.PrizeController - 奖品发放开始10001。req:{"awardNumber":"AQY1xjkUodl8LO975GdfrYUio","awardType":3,"uId":"10001"}
模拟发放爱奇艺会员卡一张:15200101232,AQY1xjkUodl8LO975GdfrYUio
15:07:44.858 [main] INFO  o.i.demo.design.PrizeController - 奖品发放完成1000115:07:44.858 [main] INFO  org.itstack.demo.test.ApiTest - 请求参数:{"uId":"10001","awardNumber":"AQY1xjkUodl8LO975GdfrYUio","awardType":3}
15:07:44.858 [main] INFO  org.itstack.demo.test.ApiTest - 测试结果:{"code":"0000","info":"发放成功"}

运⾏结果正常,满⾜当前所有业务产品需求,写的还很快。但!实在难以为维护!!!!


2.使用工厂方法模式

							工程结构图

在这里插入图片描述
活动的 商品接口
在这里插入图片描述
卡片商品服务
间接调用爱奇艺会员卡的服务,再添加其他业务
在这里插入图片描述
优惠券商品服务
在这里插入图片描述
实体商品 服务
在这里插入图片描述
仓库工厂
这里传类型可以使用 枚举类型来定义
在这里插入图片描述
开始测试

@Test
    public void test_commodity() throws Exception {
        StoreFactory storeFactory = new StoreFactory();

        // 1. 优惠券
        ICommodity commodityService_1 = storeFactory.getCommodityService(1);
        commodityService_1.sendCommodity("10001", "EGM1023938910232121323432", "791098764902132", null);

        // 2. 实物商品
        ICommodity commodityService_2 = storeFactory.getCommodityService(2);
        Map<String,String> extMap = new HashMap<String,String>();
        extMap.put("consigneeUserName", "谢飞机");
        extMap.put("consigneeUserPhone", "15200292123");
        extMap.put("consigneeUserAddress", "吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109");

        commodityService_2.sendCommodity("10001","9820198721311","1023000020112221113",new HashMap<String, String>() {{
            put("consigneeUserName", "谢飞机");
            put("consigneeUserPhone", "15200292123");
            put("consigneeUserAddress", "吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109");
        }});

        // 3. 第三方兑换卡(爱奇艺)
        ICommodity commodityService_3 = storeFactory.getCommodityService(3);
        commodityService_3.sendCommodity("10001","AQY1xjkUodl8LO975GdfrYUio",null,null);

    }

测试结果

模拟发放优惠券一张:10001,EGM1023938910232121323432,791098764902132
15:27:03.715 [main] INFO  o.i.d.d.s.i.CouponCommodityService - 请求参数[优惠券] => uId:10001 commodityId:EGM1023938910232121323432 bizId:791098764902132 extMap:null
15:27:03.767 [main] INFO  o.i.d.d.s.i.CouponCommodityService - 测试结果[优惠券]{"code":"0000","info":"发放成功"}
模拟发货实物商品一个:{"consigneeUserAddress":"吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109","consigneeUserName":"谢飞机","consigneeUserPhone":"15200292123","orderId":"1023000020112221113","sku":"9820198721311","userName":"花花","userPhone":"15200101232"}
15:27:03.774 [main] INFO  o.i.d.d.s.impl.GoodsCommodityService - 请求参数[优惠券] => uId:10001 commodityId:9820198721311 bizId:1023000020112221113 extMap:{"consigneeUserName":"谢飞机","consigneeUserAddress":"吉林省.长春市.双阳区.XX街道.檀溪苑小区.#18-2109","consigneeUserPhone":"15200292123"}
15:27:03.774 [main] INFO  o.i.d.d.s.impl.GoodsCommodityService - 测试结果[优惠券]true
模拟发放爱奇艺会员卡一张:15200101232,null
15:27:03.776 [main] INFO  o.i.d.d.s.impl.CardCommodityService - 请求参数[爱奇艺兑换卡] => uId:10001 commodityId:AQY1xjkUodl8LO975GdfrYUio bizId:null extMap:null
15:27:03.776 [main] INFO  o.i.d.d.s.impl.CardCommodityService - 测试结果[爱奇艺兑换卡]:success

那么这样的开发的好处知道后,也可以总结出来它的优点; 避免创建者与具体的产品逻辑耦合 、 满⾜单⼀职责,每⼀个业务逻辑实现都在所属⾃⼰的类中完成 、 满⾜开闭原则,⽆需更改使⽤调⽤⽅就可以
在程序中引⼊新的产品类型 。但这样也会带来⼀些问题,⽐如有⾮常多的奖品类型,那么实现的⼦
类会极速扩张。因此也需要使⽤其他的模式进⾏优化,这些在后续的设计模式中会逐步涉及到。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值