您瞧,工厂模式

工厂模式的介绍

工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式

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

这种设计模式也是 Java 开发中最常见的一种模式,它的主要意图是定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行

那是不是当多个对象,继承同一个父类,可以实例化一个工厂,用于生产这些对象呢?

分类

  • 简单工厂(一个普通类)
public class Factory{
    public static ISample creator(int which){
        // 判断返回对象
        if (which==1)
            return new SampleA();
        else if (which==2)
            return new SampleB();
    }
}

在这里插入图片描述

  • 抽象工厂(一个抽象类)
//抽象类
public abstract class Factory{
    public abstract Sample creator();
    public abstract Sample2 creator(String name);
}
//实现一个工厂
public class SimpleFactory extends Factory{
    public Sample creator(){
        .........
        return new SampleA
    }
    public Sample2 creator(String name){
        .........
        return new Sample2A
    }
}
//实现一个工厂
public class BombFactory extends Factory{
    public Sample creator(){
        ......
        return new SampleB
    }
    public Sample2 creator(String name){
        ......
        return new Sample2B
    }
}



在这里插入图片描述

案例(来自与小傅哥的重学java设计模式

简单工厂
  • 场景:积分兑换中的发放多种类型商品,有优惠券,实物,爱奇艺卡

  • 代码:

    • 创建对象:优惠卷,实物,爱奇艺
    • 使用:
      • 普通做法,通过if判断:

             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;
          }
        
      • 工厂模式

        • 创建商品接口,创建三个商品(消费卷,实物,爱奇艺)实现这个接口
        public interface ICommodity {
          
              //发送
              void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception;
          
          }
        
        
        • 实现类
        //实物
        public class GoodsCommodityService implements ICommodity{}
        
        //优惠卷
        public class CouponCommodityService implements ICommodity{}
        
        //爱奇艺
        public class CardCommodityService implements ICommodity{}
        
        • 创建一个工厂
        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("不存在的商品服务类型");
         }
        
         }
        
        
        • 使用
        @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);
        
        
             // 第三方兑换卡(爱奇艺)
             ICommodity commodityService_3 = storeFactory.getCommodityService(3);
             commodityService_3.sendCommodity("10001","AQY1xjkUodl8LO975GdfrYUio",null,null);
             
             // 实物也是这个写,标准统一,返回参数也一样
        
         }
        
        
  • 总结

    • 避免创建者与具体的产品逻辑耦合、满足单一职责,每一个业务逻辑实现都在所属自己的类中完成、满足开闭原则,无需更改使用调用方就可以在程序中引入新的产品类型 ---- 小傅哥
    • 个人理解:
      • 进行了封装,统一了入参、统一了结果。只要增加类,对于使用方基本无感,只要变更传参就行。
      • 就如上例子,如果要添加一个类型,
        • if 案例的修改:
          • 新增一个类型类
          • 要在这个awardToUser方法还要添加一个else,
          • 调用方还要了解刚新增的类
        • 使用工厂模式
          • 新增一个类,实现 ICommodity
          • 工厂方法添加一个刚实现的类
          • 调用方不改变,参数改下就行

  • 感谢

小傅哥的重学java设计模式
还有 研磨设计模式(链接) 这本书

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值