一、简介

1.1 什么是工厂方法模式

在软件开发中,我们经常需要根据不同的需求创建不同的对象或者实例,为了实现这一目的,我们通常会采用工厂模式。工厂模式是一种创建型模式,它提供了一种创建对象的最佳方式。

工厂模式分为简单工厂、工厂方法和抽象工厂三种,本文将重点介绍工厂方法模式。

工厂方法模式是一种创建型设计模式,它将对象的创建委托给工厂类。工厂类负责创建对象,并返回对象的实例。这种方式可以将对象的创建与使用分离,使得代码更加灵活。

工厂方法模式只有一个抽象产品类,且具体工厂类只能创建一个具体产品类的实例。

1.2 工厂方法模式的组成部分

  1. 抽象产品接口(Product Interface):定义产品的接口,即产品所具有的属性和方法。
  2. 具体产品类(Concrete Product):实现抽象产品接口中定义的属性和方法。
  3. 抽象工厂类(Abstract Factory):定义一个抽象工厂方法,该方法返回一个抽象产品接口类型的对象。
  4. 具体工厂类(Concrete Factory):实现抽象工厂类中定义的抽象工厂方法,返回一个具体产品类的实例。
  5. 客户端(Client):通过具体工厂类来创建具体产品类的实例,然后使用产品的属性和方法。

1.3 工厂方法模式的应用场景

  1. 需要灵活地增加新的产品类型。
  2. 需要将产品的创建与使用分离。
  3. 需要控制产品的实例化过程,避免因为创建对象时可能发生的错误。
  4. 需要在运行时动态地指定产品类型。
  5. 需要在不同的平台上,使用不同的实现。
  6. 需要支持多种风格的用户界面。
  7. 需要在框架中使用插件,以便在运行时动态地添加功能。

1.4 工厂方法模式的优缺点

1.4.1 优点:

  • 可以将产品的创建与使用分离,使得代码更加灵活。
  • 可以在不改变原有代码的情况下,灵活地增加新的产品类型。
  • 可以通过工厂类来控制产品的实例化,从而避免了因为创建对象时可能发生的错误。

1.4.2 缺点:

  • 需要定义很多的类,增加了代码的复杂度。
  • 如果产品类型很多,那么就需要定义很多的工厂类,增加了代码的复杂度。

二、示例

我们通过一个简单的例子来说明工厂方法模式的使用。

先创建一组具有相同约束的产品,比如产品A产品B产品C,它们都实现了同一个接口IProduct。同时,我们需要创建三个工厂来生产这一组产品,分别是FactoryAFactoryBFactoryC

2.1 定义一个抽象产品接口

首先定义一个抽象产品接口 IProduct,它定义了一个抽象的使用方法 use(),留给实现类去实现。

/**
 * 定义一个抽象产品接口
 */
public interface IProduct {
	// 定义一个抽象的使用方法,留给实现类去实现
	void use();
}

2.2 定义三个具体产品A、B和C

然后,定义三个具体的产品类 ProductAProductBProductC,它们实现了抽象产品接口 IProduct 中定义的 use() 方法。


产品A

import com.qfx.modules.factory.model.IProduct;

/**
 * 定义一个产品A
 */
public class ProductA implements IProduct {

	@Override
	public void use() {
		// 实现了抽象产品接口定义的use方法
		System.out.println("生产 ProductA");
	}
}

产品B

import com.qfx.modules.factory.model.IProduct;

/**
 * 定义一个产品B
 */
public class ProductB implements IProduct {

	@Override
	public void use() {
		// 实现了抽象产品接口定义的use方法
		System.out.println("生产 ProductB");
	}
}

产品C

import com.qfx.modules.factory.model.IProduct;

/**
 * 定义一个产品C
 */
public class ProductC implements IProduct {

	@Override
	public void use() {
		// 实现了抽象产品接口定义的use方法
		System.out.println("生产 ProductC");
	}
}

2.3 定义一个抽象工厂接口

接下来,定义一个抽象工厂类 FmFactory,它定义了一个抽象的工厂方法 createProduct(),留给具体的工厂类去实现。

该接口是工厂方法模式的核心,负责实现创建所有的具体产品(ProductAProductBProductC)的内部逻辑。

import com.qfx.modules.factory.model.IProduct;

/**
 * 定义工厂接口.该接口是工厂方法模式的核心,负责实现创建所有的具体产品(ProductA、ProductB、ProductC)的内部逻辑
 */
public interface FmFactory {
	// 定义一个抽象的使用方法,留给实现类去实现
    IProduct createProduct();
}

2.4 定义三个具体工厂类

然后,定义三个具体的工厂类 FactoryAFactoryBFactoryC,它们分别创建 ProductAProductBProductC 的实例。


工厂A

import com.qfx.modules.factory.abstractFactory.FmFactory;
import com.qfx.modules.factory.model.IProduct;
import com.qfx.modules.factory.model.impl.ProductA;

/**
 * 该类实现了FmFactory接口,用于生产ProductA类的实例
 */
public class FactoryA implements FmFactory {

	@Override
	public IProduct createProduct() {
		return new ProductA();
	}
}

工厂B

import com.qfx.modules.factory.abstractFactory.FmFactory;
import com.qfx.modules.factory.model.IProduct;
import com.qfx.modules.factory.model.impl.ProductB;

/**
 * 该类实现了FmFactory接口,用于生产ProductB类的实例
 */
public class FactoryB implements FmFactory {

	@Override
	public IProduct createProduct() {
		return new ProductB();
	}
}

工厂C

import com.qfx.modules.factory.abstractFactory.FmFactory;
import com.qfx.modules.factory.model.IProduct;
import com.qfx.modules.factory.model.impl.ProductC;

/**
 * 该类实现了FmFactory接口,用于生产ProductC类的实例
 */
public class FactoryC implements FmFactory {

	@Override
	public IProduct createProduct() {
		return new ProductC();
	}
}

2.5 客户端调用

最后,定义一个客户端类 FactoryMethodDemo,它通过工厂类创建产品的实例,并调用产品的方法。

先创建三个具体工厂的实例,然后通过调用它们的createProduct方法来创建具体产品的实例,并且调用它们的use方法。

import com.qfx.modules.factory.abstractFactory.FmFactory;
import com.qfx.modules.factory.abstractFactory.impl.FactoryA;
import com.qfx.modules.factory.abstractFactory.impl.FactoryB;
import com.qfx.modules.factory.abstractFactory.impl.FactoryC;
import com.qfx.modules.factory.model.IProduct;

/**
 * 工厂方法模式测试
 */
public class FactoryMethodDemo {
	
	/**
	 * 测试工厂方法模式的功能:
	 * 		它使用FactoryA、FactoryB、FactoryC三个具体工厂分别生产
	 * 		ProductA、ProductB、ProductC三个具体产品,并调用它们的use()方法。
	 */
	public static void main(String[] args) {
		// 创建FactoryA具体工厂的实例
		FmFactory factoryA = new FactoryA();
		// 通过调用createProduct()方法生产具体产品ProductA
        IProduct productA = factoryA.createProduct();
        // 调用ProductA的use()方法
        productA.use();

        // 创建FactoryB具体工厂的实例
        FmFactory factoryB = new FactoryB();
        // 通过调用createProduct()方法生产具体产品ProductB
        IProduct productB = factoryB.createProduct();
        // 调用ProductB的use()方法
        productB.use();

        // 创建FactoryC具体工厂的实例
        FmFactory factoryC = new FactoryC();
        // 通过调用createProduct()方法生产具体产品ProductB
        IProduct productC = factoryC.createProduct();
        // 调用ProductB的use()方法
        productC.use();
	}
}

执行结果:

十分钟了解设计模式四:工厂模式之工厂方法_设计模式

三、解析

  1. 以上文章介绍了如何使用 Java 代码实现工厂方法设计模式。
  2. 首先定义了一个抽象产品接口 IProduct,然后定义了三个具体的产品类,它们实现了抽象产品接口中定义的 use() 方法。
  3. 接下来定义了一个抽象工厂类 FmFactory,它定义了一个抽象的工厂方法 createProduct(),留给具体的工厂类去实现。
  4. 然后,定义了三个具体的工厂类,它们分别创建 ProductAProductBProductC 的实例。
  5. 最后,通过工厂类创建产品的实例,并调用产品的方法。

四、总结

  1. 工厂方法模式是一种创建型设计模式,它将对象的创建委托给工厂类。工厂类负责创建对象,并返回对象的实例。这种方式可以将对象的创建与使用分离,使得代码更加灵活。
  2. 组成部分包括抽象产品接口、具体产品类、抽象工厂类、具体工厂类和客户端。其中,抽象产品接口定义了产品的接口,具体产品类实现了抽象产品接口中定义的属性和方法,抽象工厂类定义了一个抽象工厂方法,具体工厂类实现了抽象工厂类中定义的抽象工厂方法,返回一个具体产品类的实例,客户端通过具体工厂类来创建具体产品类的实例,然后使用产品的属性和方法。
  3. 工厂方法模式的优点包括可以将产品的创建与使用分离,使得代码更加灵活,可以在不改变原有代码的情况下,灵活地增加新的产品类型,可以通过工厂类来控制产品的实例化,从而避免了因为创建对象时可能发生的错误。工厂方法模式的缺点包括需要定义很多的类,增加了代码的复杂度,如果产品类型很多,那么就需要定义很多的工厂类,增加了代码的复杂度。
  4. 工厂方法模式适用于需要灵活地增加新的产品类型,需要将产品的创建与使用分离,需要控制产品的实例化过程,需要在运行时动态地指定产品类型等场景。

五、与抽象工厂模式的区别

  1. 抽象工厂设计模式是工厂方法设计模式的扩展,它定义了一个抽象工厂类,它可以创建一组相关的产品,而不是单一的产品(抽象工厂模式有多个抽象产品类)。而工厂方法设计模式只定义了一个抽象工厂方法,它只能创建一种产品(工厂方法模式只有一个抽象产品类)


  1. 在抽象工厂设计模式中,客户端通过抽象工厂类来创建一组相关的产品(抽象工厂模式可以创建多个具体产品类的实例)。而在工厂方法设计模式中,客户端通过具体的工厂类来创建单一的产品(工厂方法模式只能创建一个具体产品类的实例)


  1. 抽象工厂设计模式需要定义更多的抽象类和实现类,因此它的代码结构比工厂方法设计模式更加复杂。


  1. 抽象工厂设计模式适用于创建一组相关的产品,而工厂方法设计模式适用于创建单一的产品。