# 工厂方法模式
# 参考
# 定义
简单工厂模式违背了开闭原则,扩展的时候需要对工厂逻辑进行修改。
工厂方法模式是对简单工厂模式的进一步抽象化,多了一个抽象工厂。抽象工厂提供抽象的对象实例创建方法,由具体工厂来决定实例化的对象类型。
这样就可以在不修改原有代码的情况下对应用进行扩展,满足开闭原则。
# 应用场景
比如:一个 dialog
组件,为了适配不同平台下的 UI
风格,在 android
、ios
下分别会渲染对应平台风格 button
组件。
无法预知对象的准确类别,及其依赖关系,用户需要自由扩展。
在上述场景中,
button
对象的渲染可由具体工厂决定,这样当需要扩展的时候,只需要开发新的具体工厂子类, 重写创建button
的对象的工厂方法即可。用户不用关心产品创建的具体细节。
比如在
dialog
组件中创建button
的时候,会给button
添加各种公共属性。 用户只需决定具体创建的button
对象,或者可以使用默认的button
对象,而无需关心button
的其他创建细节。
# 实现、应用思路
抽象工厂,提供了创建产品的接口,可由具体工厂重写。
具体工厂,实现、重写抽象工厂中的抽象方法,决定产品的具体创建逻辑。
抽象产品(也可以是接口),定义了产品的具体规范,描述了产品的主要特性、功能。这也是工厂模式的一大前提。
具体产品,实现了抽象产品定义的接口,由具体工厂来创建。
# 优点
避免了父类(高层模块)及其子类(子模块)的耦合。
单一职责原则,具体创建逻辑可放在子类中,更容易维护。
开闭原则,扩展只需要新增、修改子类即可。
# 缺点
如果类的个数过多,会导致代码复杂度、理解难度增加。
# 代码实例
const platforms = {
android: 'android',
ios: 'ios'
}
// 抽象产品(接口)
interface IButton {
render(): void
}
// 具体产品
class IOSButton implements IButton {
render() {
console.log('Rendering ios button.')
}
}
// 具体产品
class AndroidButton implements IButton {
render() {
console.log('Rendering android button.')
}
}
// 抽象工厂
abstract class DialogFactory {
abstract createButton(): IButton
abstract platform: string
render() {
console.log(`Render on ${this.platform}.`)
const button = this.createButton()
button.render()
}
}
// 具体工厂
class IOSDialogFactory extends DialogFactory {
platform = platforms.ios
createButton(): IButton {
return new IOSButton()
}
}
// 具体工厂
class AndroidDialogFactory extends DialogFactory {
platform = platforms.android
createButton(): IButton {
return new AndroidButton()
}
}
new IOSDialogFactory().render()
new AndroidDialogFactory().render()