工厂模式

一、 简单工厂模式

阿毅经营着一家垃圾回收公司,随着公司业务越做越大,回收垃圾的种类也越来越多,垃圾回收的相关代码如下:

public class RecycleClient {
 
    public void recycle(Thing thing) {
        RecycleHandler recycleHandler;
 
        if ("horse".equals(thing.getType())) {
            recycleHandler = new HorseRecycleHandler();
        } else if ("machinePet".equals(thing.getType())) {
            recycleHandler = new MachinePetRecycleHandler();
        } else {
            recycleHandler = new HeroRecycleHandler();
        }
 
        recycleHandler.recycle(thing);
    }
 
}
这样做存在着什么问题?RecycleClient和RecycleHandler的具体实现类高度耦合,当你需要改变或者拓展RecycleHandler,你必须修改RecycleClient。这违背的设计原则:类应该向拓展开启,向修改关闭。

而且如果我们还有RecycleClient2, RecycleClient3,还有可能会出现修改漏了或错了的情况。解决这个问题,我们只需要应用曾经提过的一条规则:将可能改变的代码从不会改变的代码中分离出来。

稍微修改以后,我们的代码变成这样:

public class RecycleClient {
    public void recycle(Thing thing) {
        RecycleHandler recycleHandler = RecycleFactory.create(thing);
        recycleHandler.recycle(thing);
    }
}
 
public class RecycleFactory {
    public static RecycleHandler create(Thing thing) {
        RecycleHandler recycleHandler;
        if ("horse".equals(thing.getType())) {
            recycleHandler = new HorseRecycleHandler();
        } else if ("machinePet".equals(thing.getType())) {
            recycleHandler = new MachinePetRecycleHandler();
        } else {
            recycleHandler = new HeroRecycleHandler();
        }
        return recycleHandler;
    }
}

这里可能会有个小疑问:我们这么做,只是将问题从RecycleClient抛到RecycleFactory,如果以后RecycleHandler需要修改,那么RecycleFactory不也是需要修改?

:是的,如果以后RecycleHandler需要修改,那么RecycleFactory也需要修改。这种情况无法避免,除非我们不使用new创建对象。但是使用Factory来创建对象解决了如果有多个Client,我们需要同时维护多份同样代码的问题。

上面讲的这个模式就是简单工厂模式。简单工厂模式,简单到很多人认为它不能算作一个设计模式。我们来看一下这个简单工厂模式在C3中的应用:

public interface RecycleOperator {
 
    RecyclePreviewResult recyclePreview(User user, List<Integer> idList);
 
    RecycleResult recycle(User user, List<Integer> idList, List<Thing> cost);
 
}
 
/**
 * 装备重生
 */
public class RO_EquipRebirth implements RecycleOperator {
 
   @Override
   public RecyclePreviewResult recyclePreview(User user, List<Integer> idList) {
      return EquipService.instance.rebirthEquipsAsPreview(user, idList);
   }
 
   @Override
   public RecycleResult recycle(User user, List<Integer> idList, List<Thing> cost) {
      return EquipService.instance.rebirthEquips(user, idList, cost);
   }
 
}
 
/**
 * 机关兽重生
 * <p>
 * Created by    on 2019/4/12.
 */
class RO_MachinePetRebirth implements RecycleOperator {
 
    @Override
    public RecyclePreviewResult recyclePreview(User user, List<Integer> idList) {
        return MachinePetService.instance.rebirthMachinePetAsPreview(user, idList);
    }
 
    @Override
    public RecycleResult recycle(User user, List<Integer> idList, List<Thing> cost) {
        return MachinePetService.instance.rebirthMachinePet(user, idList, cost);
    }
 
}
 
/**
 * 工厂方法
 */
class RecycleOperatorFactory {
 
   public static RecycleOperator createRecycleOperator(String className) {
      className = className.trim();
      className = String.format("com.cokutau.game.pjc3.mainserver.zz.recycle.RO_%s", className);
      try {
         Class<?> clazz = Class.forName(className);
         return (RecycleOperator) clazz.newInstance();
      } catch (Throwable t) {
         throw new RuntimeException(String.format("<RecycleOperatorFactory> new instance of %s error!", className), t);
      }
   }
 
}

这里需要注意的是,RecycleOperatorFactory使用了反射的方式来创建Handler,而不是使用new。这不是在炫技,通过反射来创建对象,解决了上面我们提到的“Handler需要修改时,Factory也需要修改”的问题。

二、抽象方法工厂模式

由于阿毅的垃圾回收站从不缺斤少两,生意越做越大,除了垃圾回收站以外,阿毅还开了一个宝物回收站。我们还用简单工厂模式来实现的:

public class RecycleClient2 {
    public void recycle(Thing thing) {
        RecycleHandler recycleHandler = RecycleFactory.create(thing);
        recycleHandler.recycle(thing);
    }
}
 
public class RecycleFactory2 {
    public static RecycleHandler create(Thing thing) {
        if ("baowu".equals(thing.getType())) {
            return new BaoWuRecycleHandler();
        } else {
            return new TreasureRecycleHandler();
        }
    }
}
使用简单工厂模式,我们每新增一个类型回收站,我们都得新增一个对应的工厂,这容易让我们的类的数量膨胀。解决这种问题的方法是使用抽象方法工厂模式。

The Factory Method Pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
抽象方法工厂模式定以了一个创建对象的接口,让子类来决定创建哪一个类的对象。
使用抽象方法工厂实现回收站:

public abstract class RecycleClient {
    public void recycle(Thing thing) {
        RecycleHandler recycleHandler = create(thing);
        recycleHandler.recycle(thing);
    }
 
    public abstract RecycleHandler create(Thing thing);
}
 
public class RecycleClient1 extends RecycleClient {
 
    @Override
    public RecycleHandler create(Thing thing) {
        RecycleHandler recycleHandler;
        if ("horse".equals(thing.getType())) {
            recycleHandler = new HorseRecycleHandler();
        } else if ("machinePet".equals(thing.getType())) {
            recycleHandler = new MachinePetRecycleHandler();
        } else {
            recycleHandler = new HeroRecycleHandler();
        }
        return recycleHandler;
    }
 
}
 
public class RecycleClient2 extends RecycleClient {
     
    @Override
    public RecycleHandler create(Thing thing) {
        if ("baowu".equals(thing.getType())) {
            return new BaoWuRecycleHandler();
        } else {
            return new TreasureRecycleHandler();
        }
    }
     
}

抽象工厂方法模式UML:
在这里插入图片描述

我们在AbstractFactory定义了一个操作过程(operation()),但是,操作的使什么物品由create(),也就是AbstractFactory的子类决定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值