创建型模式_02_工厂模式

分类:01_设计模式

标签:

4.2.4 工厂方法模式

4.2.4.1 工厂方法模式介绍

工厂方法模式 Factory Method pattern,属于创建型模式.

概念: 定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。

4.2.4.2 工厂方法模式原理

工厂方法模式的目的很简单,就是封装对象创建的过程,提升创建对象方法的可复用性

工厂方法模式的主要角色:

我们直接来看看工厂方法模式的 UML 图:44.jpg

4.2.4.3 工厂方法模式重构代码

为了提高代码扩展性,我们需要将简单工厂中的if分支逻辑去掉,通过增加抽象工厂(生产工厂的工厂)的方式,让具体工厂去进行实现,由具体工厂来决定实例化哪一个具体的产品对象.

抽象工厂


public interface FreeGoodsFactory {

   IFreeGoods getInstance();
}

具体工厂


public class DiscountFreeGoodsFactory implements FreeGoodsFactory {

   @Override
   public IFreeGoods getInstance() {
       return new DiscountFreeGoods();
   }
}

public class SmallGiftFreeGoodsFactory implements FreeGoodsFactory {
   @Override
   public IFreeGoods getInstance() {

       return new SmallGiftFreeGoods();
   }
}

Controller


public class DeliverController {

   /**
    * 按照类型的不同发放商品
    */
   public ResponseResult awardToUser(AwardInfo awardInfo){

       FreeGoodsFactory freeGoodsFactory = null;

       if(awardInfo.getAwardType() == 1){

           freeGoodsFactory = new DiscountFreeGoodsFactory();
       }else if(awardInfo.getAwardType() == 2){

           freeGoodsFactory = new SmallGiftFreeGoodsFactory();
       }

       IFreeGoods freeGoods = freeGoodsFactory.getInstance();

       System.out.println("=====工厂方法模式========");
       ResponseResult result = freeGoods.sendFreeGoods(awardInfo);

       return result;
   }

}

从上面的代码实现来看,工厂类对象的创建逻辑又耦合进了 awardToUser() 方法中,跟我们最初的代码版本非常相似,引入工厂方法非但没有解决问题,反倒让设计变得更加复杂了。

那怎么 来解决这个问题呢?

我们可以为工厂类再创建一个简单工厂,也就是工厂的工厂,用来创建工厂类对象。


/**
* 用简单方法模式实现: 工厂的工厂,作用是不需要每次创建新的工厂对象
* @author spikeCong
* @date 2022/9/9
**/
public class FreeGoodsFactoryMap {

   private static final Map<Integer,FreeGoodsFactory> cachedFactories = new HashMap<>();

   static{
       cachedFactories.put(1, new DiscountFreeGoodsFactory());
       cachedFactories.put(2, new SmallGiftFreeGoodsFactory());
   }

   public static FreeGoodsFactory getParserFactory(Integer type){
       if(type == 1){
           FreeGoodsFactory freeGoodsFactory = cachedFactories.get(1);
           return freeGoodsFactory;
       }else if(type ==2){
           FreeGoodsFactory freeGoodsFactory = cachedFactories.get(2);
           return freeGoodsFactory;
       }

       return null;
   }
}

Controller


/**
* 发放奖品接口
* @author spikeCong
* @date 2022/9/7
**/
public class DeliverController {

   /**
    * 按照类型的不同发放商品
    */
   public ResponseResult awardToUser(AwardInfo awardInfo){

       //根据类型获取工厂
       FreeGoodsFactory goodsFactory = FreeGoodsFactoryMap.getParserFactory(awardInfo.getAwardType());

       //从工厂中获取对应实例
       IFreeGoods freeGoods = goodsFactory.getInstance();

       System.out.println("=====工厂方法模式========");
       ResponseResult result = freeGoods.sendFreeGoods(awardInfo);
       return result;
   }
}

现在我们的代码已经基本上符合了开闭原则,当有新增的产品时,我们需要做的事情包括:

  1. 创建新的产品类,并且让该产品实现抽象产品接口

  2. 创建产品类对应的具体工厂,并让具体工厂实现抽象工厂

  3. 将新的具体工厂对象,添加到FreeGoodsFactoryMap的cachedFactories中即可,需要改动的代码改动的非常少.

4.2.4.4 工厂方法模式总结

工厂方法模优缺点

优点:

缺点:

什么时候使用工厂方法模式



修改内容