1. 意图(Intent)
定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。
简单工厂模式很简单,如果它能满足我们的需要,我觉得就不要折腾了。之所以需要引入工厂模式,是因为我们往往需要使用两个或两个以上的工厂,我们无法确定使用那个工厂,因此需要把实例化操作延迟到子类。
2. 类图(Class Diagram)
在简单工厂中,创建对象的是另一个类,而在工厂方法中,是由子类来创建对象。
下图中,Factory 有一个 doSomething() 方法,这个方法需要用到一个产品对象,这个产品对象由 factoryMethod() 方法创建。该方法是抽象的,需要由子类去实现。
3. 实现(Implementation)
工厂模式: 把实例化操作推迟到子类 的例子 [ 继承 ]
public abstract class Factory {abstract public Product factoryMethod();public void doSomething() {Product product = factoryMethod();// do something with the product}}
public class ConcreteFactoryA extends Factory {public Product factoryMethod() {return new ConcreteProductA();}//当 ConcreteFactoryA 调用 doSomething 时 product会被初始化为ConcreteProductA}
public class ConcreteFactoryB extends Factory {public Product factoryMethod() {return new ConcreteProductB();}}
public class ConcreteFactoryC extends Factory {public Product factoryMethod() {return new ConcreteProductC();}}
客户端调用:
public class Client {public static void main(String[] args) {Factory concreteProduct = new ConcreteFactoryA(); //第一步,明确工厂为A产品工厂concreteProduct.doSomething(); //对产品A执行某些操作}}
工厂模式:食物工厂 [ 接口实现 ]
public interface FoodFactory {Food makeFood(String name);}
public class ChineseFoodFactory implements FoodFactory {@Overridepublic Food makeFood(String name) {if (name.equals("A")) {return new ChineseFoodA();} else if (name.equals("B")) {return new ChineseFoodB();} else {return null;}}}
public class AmericanFoodFactory implements FoodFactory {@Overridepublic Food makeFood(String name) {if (name.equals("A")) {return new AmericanFoodA();} else if (name.equals("B")) {return new AmericanFoodB();} else {return null;}}}
其中,ChineseFoodA、ChineseFoodB、AmericanFoodA、AmericanFoodB 都派生自 Food。
客户端调用:
public class Client {public static void main(String[] args) {// 先选择一个具体的工厂FoodFactory factory = new ChineseFoodFactory();// 由第一步的工厂产生具体的对象,不同的工厂造出不一样的对象Food food = factory.makeFood("A");}}
虽然都是调用 makeFood("A") 制作 A 类食物,但是,不同的工厂生产出来的完全不一样。
核心在于,我们需要在第一步选好我们需要的工厂。
比如,我们有 LogFactory 接口,实现类有 FileLogFactory 和 KafkaLogFactory,分别对应将日志写入文件和写入 Kafka 中,显然,我们客户端第一步就需要决定到底要实例化 FileLogFactory 还是 KafkaLogFactory,这将决定之后的所有的操作。
