抽象工厂
它能创建一系列相关的对象, 而无需指定其具体类
适用场景
如果代码需要与多个不同系列的相关产品交互,但是由于无法提前获取相关信息,或者出于对未来扩展性的考虑,不希望代码基于产品的具体类进行构建,在这种情况下,可以使用抽象工厂。
如果有一个基于一组抽象方法的类,且其主要功能因此变得不明确,那么在这种情况下可以考虑使用抽象工厂模式
优/缺点
优点:
可以确保同一工厂生成的产品相互匹配
可以避免客户端和具体产品代码的耦合
单一职责原则。可以将产品生成代码抽取到同一位置,使得代码易于维护。
开闭原则。向应用程序中引入新产品变体时,无需修改客户端代码。
缺点:
由于采用该模式需要向应用中引入众多接口和类,代码可能会比之前更加复杂
对比其他模式
早期都会使用工厂方法模式(较为简单,而且可以更方便地通过子类进行定制),随后演化为使用抽象工厂模式、原型模式或生成器模式(更灵活但更加复杂)
生成器重点关注如何分步生成复杂对象。抽象工厂专门用于生产一系列相关对象。抽象工厂会马上返回产品,生成器则允许你在获取产品前执行一些额外构造步骤
抽象工厂模式通常基于一组工厂方法,但也可以使用原型模式来生成这些类的方法
只需对客户端代码隐藏子系统创建对象的方式时,可以使用抽象工厂来代替外观模式
可以将抽象工厂和桥接模式搭配使用。如果由桥接定义的抽象只能与特定实现合作,这一模式搭配就非常有用。在这种情况下,抽象工厂可以对这些关系进行封装,并且对客户端代码隐藏其复杂性
抽象工厂、生成器和原型都可以用单例模式来实现
实现示例
interface GUIFactory {
createButton(): Button;
createCheckbox(): Checkbox;
}
class Button {
render(): void {
// do something
console.log(this.name);
}
}
class Checkbox {
render(): void {
// do something
console.log(this.name);
}
}
class LightThemeButton extends Button {}
class LightThemeCheckbox extends Checkbox {}
class LightThemeFactory implements GUIFactory {
createButton(): LightThemeButton {
return new LightThemeButton();
}
createCheckbox(): LightThemeCheckbox {
return new LightThemeCheckbox();
}
}
class Page {
guiFactory: GUIFactory;
constructor(guiFactory: GUIFactory) {
this.guiFactory = guiFactory;
}
render() {
const button = this.guiFactory.createButton();
button.render();
const checkbox = this.guiFactory.createCheckbox();
checkbox.render();
}
}
function main() {
const config = readApplicationConfigFile();
let guiFactory: GUIFactory;
if (config.theme === "Dark") {
guiFactory = new DarkThemeFactory();
} else {
guiFactory = new LightThemeFactory();
}
const page = new Page(guiFactory);
page.render();
}
// 新增一个主题
class DarkThemeButton extends Button {}
class DarkThemeCheckbox extends Checkbox {}
class DarkThemeFactory implements GUIFactory {
createButton(): DarkThemeButton {
return new DarkThemeButton();
}
createCheckbox(): DarkThemeCheckbox {
return new DarkThemeCheckbox();
}
}
最后更新于