工厂方法模式是什么?
工厂方法模式(Factory Method Pattern)是一种创建型的设计模式,它的指导思想是在父类提供一个用于创建产品的接口,但让子类来决定创建何种具体的产品。
UML 类图
用 UML 类图来描述工厂方法模式的结构,在模式中各个角色之间的关系:
根据上图,总结了模式中各个角色的职责以及它们之间的关系:
- 产品抽象出一组接口,对于创建者及其子类构建的对象而言,这些接口都是通用的。
- 具体产品是对产品接口的不同实现。
- 创建者会声明返回产品对象的工厂方法,而方法返回的对象类型必须与产品接口相匹配。需要了解的是,尽管它的名字是创建者,但它最主要的职责并不一定就是创建产品。一般来说,创建者类会包含一些与产品相关的业务逻辑,工厂方法帮助我们将这些逻辑与具体的产品类解耦。
- 具体创建者重写基础的工厂方法,使其返回不同类型的产品。需要注意的是,每次调用工厂方法时并不一定都要创建新的实例。工厂方法也可以返回缓存、对象池或其他来源的已有对象。
案例
让我们通过一个案例来帮助我们理解工厂方法模式。假设有如下情景:在各大笔记本专卖店中,有笔记本产品展示以供售卖。在苹果商店展示的是 Mac Book,在微软商城展示的是 Surface 等等。
借助上述的模式结构,我们先梳理一下情景中的各个角色。首先,产品这一角色是笔记本,它是对各种类型的笔记本的抽象。
public interface Laptop {void startup();void work();void shutdown();// other methods}
而 MacBook、Surface 是具体的产品。
public class MacBook implements Laptop {@Overridepublic void startup() {System.out.println("Starting up the MacBook.");}@Overridepublic void work() {System.out.println("The MacBook is working.");}@Overridepublic void shutdown() {System.out.println("Shutting down the MacBook.");}// other methods}public class Surface implements Laptop {// ...}
创造者这一角色是笔记本专卖店,它声明了一个接口用来创建笔记本,而究竟创建何种类型的笔记本,则由具体的专卖店来控制。
public abstract class LaptopStore {public abstract Laptop createLaptop();public void display(Laptop laptop) {laptop.startup();laptop.work();}// other business logic}
而苹果商店和微软商城等则是具体的创建者。
public class AppleStore extends LaptopStore {@Overridepublic Laptop createLaptop() {return new MacBook();}}public class MicrosoftStore extends LaptopStore {@Overridepublic Laptop createLaptop() {return new Surface();}}
最后,我们通过一个用例来模拟一下上述的情景:
public class FactoryMethodMain {public static void main(String[] args) {String storeType = args != null && args.length > 0 ? args[0] : null;LaptopStore laptopStore;if ("Apple".equalsIgnoreCase(storeType)) {laptopStore = new AppleStore();} else if ("Microsoft".equalsIgnoreCase(storeType)) {laptopStore = new MicrosoftStore();} else {throw new IllegalArgumentException("Unknown Laptop Store.");}Laptop laptop = laptopStore.createLaptop();laptopStore.display(laptop);}}
案例源码
可在 GitHub 上查看上述案例的完整代码。
优点与不足
工厂方法模式具有如下优点:
- 可以避免创建者与具体产品之间的耦合。
- 遵循单一职责原则,将创建产品的代码放在程序的单一位置,从而使得代码更容易维护。
- 遵循开闭原则,无需修改现有的客户端代码,就可以在程序中引入新的产品。
但它也有不足之处:
- 采用工厂方法模式会引入许多新的子类,代码可能会因此变得更复杂。
参考资料
以下是本文参考的资料:
