工厂模式是一种创建型模式,就像其名字一样,工厂对外创建生成一批对象。这些对象具有一些相似性,这些对象具有一些对外的相同接口,如都有paint方法。工厂模式不修改原有的代码,通过添加额外功能的类扩展功能。如何生产对象包含以下3种方式:
- 简单工厂模式 把对象的创建放到一个工厂类中,通过参数来创建不同的对象。
- 工厂方法模式 在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。同一种物品扩展不同的物品类型,通过添加子类实现。如Button,已经有Windows Button子类,想增加一个Web Button类,增加一个子类Web Button类。
- 抽象工厂模式 定义一个创建一系列相关或互相依赖对象的接口,抽象出工厂类。可以增加扩展新的工厂类。这种模式处理更复杂的对象关系,多种不同的物品对应不同的类型。抽象工厂模式比工厂方法模式更向上一层抽象,加一层向上的分类。 如有Button,Checkbox这两种组件,会在Windows,Mac平台上展示。则有4种组合可能,Windows Button,Windows Checkbox,Mac Button,Mac Checkbox。抽象出平台接口,Windows和Mac两类,然后分别处理每一平台的不同的组件创建。
工厂方法模式
- 产品 (Product) 将会对接口进行声明。 对于所有由创建者及其子类构建的对象, 这些接口都是通用的。
- 具体产品 (Concrete Products) 是产品接口的不同实现。
- 创建者 (Creator) 类声明返回产品对象的工厂方法。 该方法的返回对象类型必须与产品接口相匹配。
- 具体创建者 (Concrete Creators) 将会重写基础工厂方法, 使其返回不同类型的产品。
例子:
// 创建者类声明的工厂方法必须返回一个产品类的对象。创建者的子类通常会提供
// 该方法的实现。
class Dialog is
// 创建者还可提供一些工厂方法的默认实现。
abstract method createButton():Button
// 请注意,创建者的主要职责并非是创建产品。其中通常会包含一些核心业务
// 逻辑,这些逻辑依赖于由工厂方法返回的产品对象。子类可通过重写工厂方
// 法并使其返回不同类型的产品来间接修改业务逻辑。
method render() is
// 调用工厂方法创建一个产品对象。
Button okButton = createButton()
// 现在使用产品。
okButton.onClick(closeDialog)
okButton.render()
// 具体创建者将重写工厂方法以改变其所返回的产品类型。
class WindowsDialog extends Dialog is
method createButton():Button is
return new WindowsButton()
class WebDialog extends Dialog is
method createButton():Button is
return new HTMLButton()
// 产品接口中将声明所有具体产品都必须实现的操作。
interface Button is
method render()
method onClick(f)
// 具体产品需提供产品接口的各种实现。
class WindowsButton implements Button is
method render(a, b) is
// 根据 Windows 样式渲染按钮。
method onClick(f) is
// 绑定本地操作系统点击事件。
class HTMLButton implements Button is
method render(a, b) is
// 返回一个按钮的 HTML 表述。
method onClick(f) is
// 绑定网络浏览器的点击事件。
class Application is
field dialog: Dialog
// 程序根据当前配置或环境设定选择创建者的类型。
method initialize() is
config = readApplicationConfigFile()
if (config.OS == "Windows") then
dialog = new WindowsDialog()
else if (config.OS == "Web") then
dialog = new WebDialog()
else
throw new Exception("错误!未知的操作系统。")
// 当前客户端代码会与具体创建者的实例进行交互,但是必须通过其基本接口
// 进行。只要客户端通过基本接口与创建者进行交互,你就可将任何创建者子
// 类传递给客户端。
method main() is
this.initialize()
dialog.render()
抽象工厂模式
- 抽象产品 (Abstract Product) 为构成系列产品的一组不同但相关的产品声明接口。
- 具体产品 (Concrete Product) 是抽象产品的多种不同类型实现。
- 抽象工厂 (Abstract Factory) 接口声明了一组创建各种抽象产品的方法。
- 具体工厂 (Concrete Factory) 实现抽象工厂的构建方法。 每个具体工厂都对应特定产品变体, 且仅创建此种产品变体。
例子:
// 抽象工厂接口声明了一组能返回不同抽象产品的方法。这些产品属于同一个系列
// 且在高层主题或概念上具有相关性。同系列的产品通常能相互搭配使用。系列产
// 品可有多个变体,但不同变体的产品不能搭配使用。
interface GUIFactory is
method createButton():Button
method createCheckbox():Checkbox
// 具体工厂可生成属于同一变体的系列产品。工厂会确保其创建的产品能相互搭配
// 使用。具体工厂方法签名会返回一个抽象产品,但在方法内部则会对具体产品进
// 行实例化。
class WinFactory implements GUIFactory is
method createButton():Button is
return new WinButton()
method createCheckbox():Checkbox is
return new WinCheckbox()
// 每个具体工厂中都会包含一个相应的产品变体。
class MacFactory implements GUIFactory is
method createButton():Button is
return new MacButton()
method createCheckbox():Checkbox is
return new MacCheckbox()
// 系列产品中的特定产品必须有一个基础接口。所有产品变体都必须实现这个接口。
interface Button is
method paint()
// 具体产品由相应的具体工厂创建。
class WinButton implements Button is
method paint() is
// 根据 Windows 样式渲染按钮。
class MacButton implements Button is
method paint() is
// 根据 macOS 样式渲染按钮
// 这是另一个产品的基础接口。所有产品都可以互动,但是只有相同具体变体的产
// 品之间才能够正确地进行交互。
interface Checkbox is
method paint()
class WinCheckbox implements Checkbox is
method paint() is
// 根据 Windows 样式渲染复选框。
class MacCheckbox implements Checkbox is
method paint() is
// 根据 macOS 样式渲染复选框。
// 客户端代码仅通过抽象类型(GUIFactory、Button 和 Checkbox)使用工厂
// 和产品。这让你无需修改任何工厂或产品子类就能将其传递给客户端代码。
class Application is
private field factory: GUIFactory
private field button: Button
constructor Application(factory: GUIFactory) is
this.factory = factory
method createUI() is
this.button = factory.createButton()
method paint() is
button.paint()
// 程序会根据当前配置或环境设定选择工厂类型,并在运行时创建工厂(通常在初
// 始化阶段)。
class ApplicationConfigurator is
method main() is
config = readApplicationConfigFile()
if (config.OS == "Windows") then
factory = new WinFactory()
else if (config.OS == "Mac") then
factory = new MacFactory()
else
throw new Exception("错误!未知的操作系统。")
Application app = new Application(factory)
webpack工厂方法模式
// Compilation.js
_addModuleChain(context, dependency, onModule, callback) {
// ...
// 工厂方法模式
const moduleFactory = this.dependencyFactories.get(Dep);
moduleFactory.create(...); // XxxModuleFactory
}
其中dependencyFactories可能会获取到多种模块工厂(normalModuleFactory、dllModuleFactory、multiModuleFactory)。 normalModuleFactory、dllModuleFactory、multiModuleFactory对外提供统一create接口,用于创建对应类型的module对象。 normalModule、dllModule、multiModule都继承了Module类,共同有Module类的方法,并且各自实现了一些相同的方法(如build方法),外部接口调用时统一调用,不用区分module类型。