工厂模式

工厂模式

工厂模式也是最常用的模式之一,是创建型模式的一种。父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。

工厂模式的思想是提供一个创建对象的结构,让子类决定去实例化哪一个工厂,并隐蔽了具体的实现逻辑。

生活中最常见的就是购物,当我们去买东西时,去不同的品牌店就可以买到对应的品牌,我们不用考虑它的实现过程。还有就是我们在网上参加活动,中奖后可以选择不同的奖品,这里也可以用到工厂模式来实现。

多类型奖品发放实现工厂模式

假设商品提供三种接口

//优惠券接口
CouponResult sendCoupon(String uId, String couponNumber, String uuid);
//实物接口
Boolean deliverGoods(DeliverReq req);
//第三方兑换券接口
void grantToken(String phoneNumber, String cardId);

定义一个共同的接口,所有商品走这个接口来保证参数的统一性。

public interface Commodity {
    /**
     * 
     * @param uid  用户id
     * @param commodityId 商品id
     * @param bizId  业务id
     * @param extData 其他信息
     */
   void sendCommodity(String uid, String commodityId, String bizId, Map<String,String> extData);

}

实现优惠券发放接口

public class CouponCommodityService implements Commodity {

    private Logger logger = LoggerFactory.getLogger(CouponCommodityService.class);

    private CouponService couponService = new CouponService();

    public void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extData) throws Exception {
        CouponResult couponResult = couponService.sendCoupon(uId, commodityId, bizId);
        logger.info("请求参数[优惠券] => uId:{} commodityId:{} bizId:{} extData:{}", uId, commodityId, bizId, JSON.toJSON(extData));
        logger.info("测试结果[优惠券]:{}", JSON.toJSON(couponResult));
        if (!"0000".equals(couponResult.getCode())) throw new RuntimeException(couponResult.getInfo());
    }

}

实现实物发放接口

public class GoodsCommodityService implements Commodity {

    private Logger logger = LoggerFactory.getLogger(GoodsCommodityService.class);

    private GoodsService goodsService = new GoodsService();

    public void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extData) throws Exception {
        DeliverReq deliverReq = new DeliverReq();
        deliverReq.setUserName(queryUserName(uId));
        deliverReq.setUserPhone(queryUserPhoneNumber(uId));
        deliverReq.setSku(commodityId);
        deliverReq.setOrderId(bizId);
        deliverReq.setConsigneeUserName(extData.get("consigneeUserName"));
        deliverReq.setConsigneeUserPhone(extData.get("consigneeUserPhone"));
        deliverReq.setConsigneeUserAddress(extData.get("consigneeUserAddress"));

        Boolean isSuccess = goodsService.deliverGoods(deliverReq);

        logger.info("请求参数[优惠券] => uId:{} commodityId:{} bizId:{} extData:{}", uId, commodityId, bizId, JSON.toJSON(extData));
        logger.info("测试结果[优惠券]:{}", isSuccess);

        if (!isSuccess) throw new RuntimeException("实物商品发放失败");
    }

    private String queryUserName(String uId) {
        return "李华";
    }

    private String queryUserPhoneNumber(String uId) {
        return "123456789";
    }

}

实现第三方兑换接口

public class CardCommodityService implements Commodity {

    private Logger logger = LoggerFactory.getLogger(CardCommodityService.class);

    
    private IQiYiCardService iQiYiCardService = new IQiYiCardService();

    public void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extData) throws Exception {
        String mobile = queryUserMobile(uId);
        iQiYiCardService.grantToken(mobile, bizId);
        logger.info("请求参数[视频兑换卡] => uId:{} commodityId:{} bizId:{} extData:{}", uId, commodityId, bizId, JSON.toJSON(extData));
        logger.info("测试结果[视频兑换卡]:success");
    }

    private String queryUserMobile(String uId) {
        return "123456789";
    }

}

创建工厂(看样子有点像简单工厂)

public class StoreFactory {

    public ICommodity getCommodityService(Integer commodityType) {
    	switch(commodityType){
    		case 1:return new CouponCommodityService();
    		case 2:return new GoodsCommodityService();
    		case 3:return new CardCommodityService();
    		default:
    		throw new RuntimeException("不存在的商品服务类型");
    
    }

}

测试

@Test
public void test_commodity() throws Exception {
    StoreFactory storeFactory = new StoreFactory();
   
    Commodity commodityService = storeFactory.getCommodityService(1);
    commodityService_1.sendCommodity("001", "EST43254264542", "47443272432888865", null);
   
}
模拟发放优惠券一张:001,EST43254264542,47443272432888865
请求参数[优惠券] => uId:001 commodityId:EST43254264542 bizId:47443272432888865 extData
测试结果[优惠券]:{"code":"0000","info":"发放成功"}

总结:工厂模式避免创建者与具体的产品逻辑耦合 、 满足单⼀职责,每⼀个业务逻辑实现都在所属自己的类中完成 、 满足开闭原则,无需更改使用调用方就可以在程序中引入新的产品类型 。但这样也会带来⼀些问题,比如有非常多的奖品类型,那么实现的子类会极速扩张。因此也需要使用其他的模式进行优化,这些在后续的设计模式中会逐步涉及到。

上一篇:day11 Linux用户管理


下一篇:idea中搭建mybatis框架