简单工厂模式(Simple Factory Pattern)
简介
简单工厂模式是一种非常常用的设计模式,但是并不属于GoF中的23中设计模式。简单设计模式有很多种实现方式。
本文我们就来讨论简单工厂模式的实现方式,以及如何借助Spring实现一个扩展性很好的简单工厂模式。
定义
DEFINITION
- creates objects without exposing the instantiation logic to the client.
- refers to the newly created object through a common interface
- 创建对象但是不想客户端暴露对象实例化的逻辑
- 通过通用接口引用新创建的对象
实现

- Product:商品接口。
- ConcreteProductA和ConcreteProductB:分别为商品的两个实现。
- Factory:工厂,创建商品实例,并将商品实例返回给客户端供客户端调用。
- Client:客户端,商品的使用者。
- Product
- ConcreteProduct
- Factory
- Client
public interface Product {
void doSomething();
}
public class ConcreteProductA implements Product {
@Override
public void doSomething() {
System.out.println("This is product A");
}
}
public class ConcreteProductB implements Product {
@Override
public void doSomething() {
System.out.println("This is product B");
}
}
public class Factory {
public Product createProduct(String type) {
if (type.equalsIgnoreCase("A")) {
return new ConcreteProductA();
} else if (type.equalsIgnoreCase("A")) {
return new ConcreteProductB();
}
throw new RuntimeException("不支持的类型");
}
}
public class Client {
public static void main(String[] args) {
Factory factory = new Factory();
Product product = factory.createProduct("A");
product.doSomething();
}
}
其实简单工厂模式的核心就是下面的代码
if (type.equalsIgnoreCase("A")) {
return new ConcreteProductA();
} else if (type.equalsIgnoreCase("A")) {
return new ConcreteProductB();
}
通过判断传入的参数,然后根据参数创建不同的对象。
这种方式的弊端就是我们没增加一种Product的实现,都需要修改工厂类。下面我们将一种不用修改工厂类的方法。
将产品注册到工厂
Product、ConcreteProductA、ConcreteProductB不变。
- Factory
- Client
public class Factory {
public Map<String, Class<? extends Product>> classMap = new HashMap<>();
public void register(String id, Class<? extends Product> clz) {
System.out.println("注册产品:" + id + "," + clz);
this.classMap.put(id, clz);
}
public Product createProduct(String type) {
Class<? extends Product> clz = this.classMap.get(type);
if (clz != null) {
try {
return clz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
throw new RuntimeException("不支持的类型");
}
}
public class Client {
public static void main(String[] args) {
Factory factory = new Factory();
factory.register("A", ConcreteProductA.class);
factory.register("B", ConcreteProductB.class);
Product product = factory.createProduct("A");
product.doSomething();
}
}
这里我们让客户端在使用的时候将Product实现类注册到工厂中,然后在Client调用的Factory.createProduct()时,找到对应的类,然后通过Java的反射机制实例化类,并返回给客户端。
这种方式我们增加Product实现类就不需要更改Factory中的源代码了。
这里可能会有人纠结,我们虽然没有改
Factory的源代码,但是更改了Client的源代码啊。这同样违反了开闭原则啊。但是其实不是这样的,Client作为使用者,需求的变更必然会伴随着使用者的变更。而且我们在实际项目中可以通过Spring来实现工厂和客户端都不需要修改源代码。