工厂方法模式是什么?
工厂方法模式(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 {
@Override
public void startup() {
System.out.println("Starting up the MacBook.");
}
@Override
public void work() {
System.out.println("The MacBook is working.");
}
@Override
public 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 {
@Override
public Laptop createLaptop() {
return new MacBook();
}
}
public class MicrosoftStore extends LaptopStore {
@Override
public 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 上查看上述案例的完整代码。
优点与不足
工厂方法模式具有如下优点:
- 可以避免创建者与具体产品之间的耦合。
- 遵循单一职责原则,将创建产品的代码放在程序的单一位置,从而使得代码更容易维护。
- 遵循开闭原则,无需修改现有的客户端代码,就可以在程序中引入新的产品。
但它也有不足之处:
- 采用工厂方法模式会引入许多新的子类,代码可能会因此变得更复杂。
参考资料
以下是本文参考的资料: