一、 简单工厂模式
阿毅经营着一家垃圾回收公司,随着公司业务越做越大,回收垃圾的种类也越来越多,垃圾回收的相关代码如下:
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的子类决定。