概述
工厂模式是创建型设计模式的代表,其设计的思想就是将类的创建和使用隔离开来,用一个专门的工厂类来创建对象,这样就将使用的类和创建的类进行了解耦。引入了工厂类以后,程序的目标就是如何在新增了被创建对象的时候,在最小的改动中完成新的扩展功能,这种扩展主要体现在以下两个方面:
- 客户端创建和使用工厂类的扩展,也就是扩展中尽量做到客户端不修改
- 工厂类创建类的时候的扩展,也就是扩展中工厂类不修改
为了解决以上两个问题,不同的解决思路演化成了不同的工厂模式,用来解决不同的问题。
简单工厂模式(Simple Factory)
定义
简单工厂设计模式就是单纯的将创建类的功能进行解耦出来,将创建对象的功能放到工厂类中去,客户端直接调用工厂类便可以得到要使用的对象。简单工厂的本质就是选择创建。在这个过程中,如果需要在多个被创建类中选择一个去创建,客户端就要指定到底要创建哪一个。
代码示例
我们以创建一类产品对象的不同产品为例,类简单模拟简单工厂模式的使用。
- 先创建一个Product的接口类
public interface Product {
void operate();
}
- 实现两个产品ProductA和ProductB
public class ProductA implements Product {
@Override
public void operate() {
System.out.println("productA");
}
}
public class ProductB implements Product {
@Override
public void operate() {
System.out.println("productB");
}
}
- 创建简单工厂类,我们以传入一个string标记和传入Class对象的两种方式来举例,当然也可以用配置文件的方式或者其他的方法。
public class SimpleFactory {
/**
* 创建对象的方式一:
* 客户端传入一个标记,工厂类根据标记来创建对象
* @param productFlag : 创建标记
* @return : 被创建的对象
*/
public static Product createProduct(String productFlag) {
if (productFlag == null || "".equals(productFlag.trim())) {
return null;
}
productFlag = productFlag.trim();
if ("productA".equals(productFlag)) {
return new ProductA();
}
if ("productB".equals(productFlag)) {
return new ProductB();
}
return null;
}
/**
* 创建对象的方式二:
* 客户端传入被创建对象的class类,工厂类根据反射去创建对象
* @param clazz : 被创建对象的class类
* @return : 被创建的对象
*/
public static Product createProduct(Class<? extends Product> clazz) {
if (null == clazz) {
return null;
}
try {
return clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
- 客户端使用
public class Client {
@Test
public void test1() {
Product product = SimpleFactory.createProduct("productA");
product.operate();
}
@Test
public void test2() {
Product product = SimpleFactory.createProduct(ProductB.class);
product.operate();
}
}
UML类图
总结
简单工厂模式对客户端和创建对象的逻辑进行了简单的隔离,并没有做到完全的解耦,从示例中我们可以看到,客户端在使用的过程中,还是要感知对象的存在,同时工厂类在创建对象的时候,也要感知对象的存在,因此,创建解耦的两边都没有做到完全的解耦。但是简单工厂模式只需要增加一个工厂类,而且如果被创建的对象比较简单的话,完全可以用静态方法来写,这样对于客户端使用和代码的可读性方面都是非常清晰的。
工厂方法模式(Factory Method)
定义
工厂方法模式在简单工厂的基础上,着重解决了工厂类和创建的对象之间的扩展问题。具体实现思路是:讲工厂对象作为一个接口或者抽象类,让工厂的子类去实现具体要创建哪个对象。工厂方法的本质就是将具体的创建逻辑让子类去实现,这样在新增了对象的时候,同步新增对应的工厂类即可,客户端就不需要感知具体的对象了。
代码示例
我们在简单工厂中Product接口和ProductA、ProductB两个实现类的基础上,进行代码示例编写
- 新增一个工厂方法的接口
public interface ProductFactoryMethod {
Product createProduct();
}
- 创建两个ProductFactoryMethod的实现类ProductAFactory和ProductBFactory,用来对应创建ProductA和ProductB对象
public class ProductAFactory implements ProductFactoryMethod {
@Override
public Product createProduct() {
return new ProductA();
}
}
public class ProductBFactory implements ProductFactoryMethod {
@Override
public Product createProduct() {
return new ProductB();
}
}
- 客户端代码如下
public class Client {
@Test
public void test() {
ProductFactoryMethod factoryMethod = new ProductAFactory();
factoryMethod.createProduct().operate();
}
}
UML类图
总结
工厂方法模式在简单工厂的基础上,讲具体对象的创建交到工厂创建类的子类中去实现,对客户端和产品对象进行了解耦,使的客户端在不感知产品的对象的前提下,对程序进行了扩展。虽然客户端不用感知产品,但是需要感知具体的工厂类,但是这种感知可以在新增了产品对象需要扩展时,用配置文件或者数据库的方式,进行扩展,使的客户端和产品对象不再耦合成为了可能。
抽象工厂模式(Abstract Factory)
定义
抽象工厂模式的主要目的是为了创建有相互依赖的产品族的。在现实生活中,有的对象是要组合起来使用的,两个类型的产品有着相互的依赖关系,比如intel的CPU就必须装在支持intel的主板上,同理AMD的CPU也要装在支持AMD的主板上才能工作,虽然对于产品来说,有CPU和主板两类,但是其具体的实现有特定的依赖关系。解决这种问题,我们可以用到抽象工厂模式,先定义一个抽象的工厂类,里面可以创建相互关联的产品类型,在具体实现的工厂子类中可以实现相互依赖的产品。比如上面cpu和主板的例子中,我们可以先定义一个工厂接口,其中有两个方法,一个是创建CPU的方法,一个是创建主板的方法,在intel的产品工厂实现类中可以穿件intel的CPU和主板,在AMD的工厂实现类中可以创建AMD的CPU和主板,这样不同工厂的实现类创建出来的产品就是相互关联好的,不会出现不一致的情况。
代码示例
- 新建ProductA和ProductB两类产品的接口
public interface ProductA {
void operateA();
}
public interface ProductB {
void operateB();
}
- 给ProductA实现两个产品ProductA1和ProductA2,同理给ProductB实现两个产品ProductB1和ProductB2,其中ProductA1和ProductB1有依赖关系,ProductA2和ProductB2有依赖关系。
public class ProductA1 implements ProductA {
@Override
public void operateA() {
System.out.println("operateA1");
}
}
public class ProductA2 implements ProductA {
@Override
public void operateA() {
System.out.println("operateA2");
}
}
public class ProductB1 implements ProductB {
@Override
public void operateB() {
System.out.println("operateB1");
}
}
public class ProductB2 implements ProductB {
@Override
public void operateB() {
System.out.println("operateB2");
}
}
- 创建一个抽象工厂的接口,可以创建ProductA和ProductB两类产品
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
- 创建两个AbstractFactory工厂的实现类Product1Factory和Product2Factory,用来具体创建产品对象
public class Product1Factory implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ProductA1();
}
@Override
public ProductB createProductB() {
return new ProductB1();
}
}
public class Product2Factory implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ProductA2();
}
@Override
public ProductB createProductB() {
return new ProductB2();
}
}
- 客户端使用
public class Client {
@Test
public void testProductFactory1() {
AbstractFactory factory = new Product1Factory();
userProduct(factory);
}
@Test
public void testProductFactory2() {
AbstractFactory factory = new Product2Factory();
userProduct(factory);
}
private void userProduct(AbstractFactory factory) {
ProductA productA = factory.createProductA();
productA.operateA();
ProductB productB = factory.createProductB();
productB.operateB();
}
}
UML类图
总结
抽象工厂模式是为了解决有相互依赖产品族的问题,如果把相互依赖的产品看成是一类产品对象的话,抽象工厂就成了工厂方法模式。
后记
个人总结,欢迎转载、评论、批评指正