抽象工厂模式
抽象工厂模式就是:围绕一个超级工厂类,创建其他工厂类;再围绕工厂类,创建实体类。相较于传统的工厂模式,它多出了一个超级工厂类。
什么是抽象工厂模式?
抽象工厂模式就是:围绕一个超级工厂类,创建其他工厂类;再围绕工厂类,创建实体类。
相较于传统的工厂模式,它多出了一个超级工厂类。
它的优缺点与工厂模式类似,这里不再冗赘它的优缺点,下面直接谈一下实现吧。
如何实现抽象工厂模式?
为了让目标更清晰,就实现下面的示意图:
准备实体类
按照之前的做法,这里我们实现几个实体类:Cat 和 Dog 一组、Male 和 Female 一组。
class Dog {
run() {
console.log("狗");
}
}
class Cat {
run() {
console.log("猫");
}
}
class Male {
run() {
console.log("男性");
}
}
class Female {
run() {
console.log("女性");
}
}
准备工厂类
假设 Cat 和 Dog,属于 Animal 工厂的产品;Male 和 Female 属于 Person 工厂的产品。所以需要实现 2 个工厂类:Animal 和 Person。
由于工厂类上面还有个超级工厂,为了方便工厂类生产实体,工厂类应该提供生产实体的方法接口。
为了更好的约束工厂类的实现,先实现一个抽象工厂类:
class AbstractFactory {
getPerson() {
throw new Error("子类请实现接口");
}
getAnimal() {
throw new Error("子类请实现接口");
}
}
接下来,Animal 和 Dog 实现抽象工厂类(AbstractFactory):
class PersonFactory extends AbstractFactory {
getPerson(person) {
person = person.toLocaleLowerCase();
switch (person) {
case "male":
return new Male();
case "female":
return new Female();
default:
break;
}
}
getAnimal() {
return null;
}
}
class AnimalFactory extends AbstractFactory {
getPerson() {
return null;
}
getAnimal(animal) {
animal = animal.toLocaleLowerCase();
switch (animal) {
case "cat":
return new Cat();
case "dog":
return new Dog();
default:
break;
}
}
}
实现“超级工厂”
超级工厂的实现没什么困难,如下所示:
class Factory {
constructor(choice) {
choice = choice.toLocaleLowerCase();
switch (choice) {
case "person":
return new PersonFactory();
case "animal":
return new AnimalFactory();
default:
break;
}
}
}
分析小结
优点
- 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
- 易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。
- 它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中
缺点
- 产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
- 如果要增加一个项目表Project,那么就需要增加三个类,IProject,MySQLProject,OracleProject,还需要改动IFactory,MySQLFactory,OracleFactory才可以完全实现。这样是很糟糕的。编程是门艺术,这样大批量的改动,显然是非常丑陋的做法。
如何改善?
可以使用简单工厂来改进抽象工厂。去除IFactory、MySQLFactory、OracleFactory三个工厂类,用一个DataAcces类代替,用一个简单工厂模式来实现。具体实现代码省略,有兴趣的小伙伴可以自己实现。
使用场景
- QQ 换皮肤,一整套一起换。
- 生成不同操作系统的程序。
特点
- 产品族难扩展
- 产品等级易扩展。