抽象工厂模式铜工厂方法模式一样,也是有抽象工厂、具体工厂、抽象产品、具体产品4
个要素构成,但是抽象工厂中方法个数不同,抽象产品的个数也不同。那么这篇文章主要介绍一下抽象工厂。
说到抽象工厂不知道有没有些许的迷茫,笔者在刚刚接触的时候却是很迷茫的,其中最难理解的可能就是抽象
。什么是抽象?
抽象:抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征的过程。具体地说,抽象就是人们在实践的基础上,对于丰富的感性材料通过去粗取精、去伪存真、由此及彼、由表及里的加工制作,形成概念、判断、推理等思维形式,以反映事物的本质和规律的方法。 ——节选自百度百科
笔者的理解的抽象则是抽离实物的本质,去掉其中不中要的部分。希望大家也能对抽象有一个简单的理解,既然理解了抽象,那么抽象工厂模式自然也是如此,文章中开头说到抽象工厂模式铜工厂方法模式一样,其实也不大相同,其实抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
什么是抽象工厂模式
抽象工厂模式:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。然而笔者理解的抽象工厂是这样的,为创建一组相关或依赖的对象提供一个接口,而且无需指定他们的具体类。
使用抽象工厂模式一般要满足以下条件。
- 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
- 系统一次只可能消费其中某一族产品,即同族的产品一起使用。
抽象工厂定义了用于创建不同产品的接口,但将实际的创建工作留给了具体工厂类。每个工厂类型都对应一个特定的产品变体。在创建产品时,客户端代码调用的是工厂对象的构建方法,而不是直接调用构造函数(new
操作符)。由于一个工厂对应一种产品变体,因此它创建的所有产品都可相互兼容。客户端代码仅通过其抽象接口与工厂和产品进行交互。该接口允许同一客户端代码与不同产品进行交互。 你只需创建一个具体工厂类并将其传递给客户端代码即可。
抽象工厂模式优缺点
抽象工厂更像一个复杂版本的策略模式,策略模式通过更换策略来改变处理方式或者结果;而抽象工厂的客户端,通过更改工厂还改变结果。所以在使用的时候,就使用客户端和更换工厂,而看不到产品本身。
工厂方法目的是生产产品,所以能看到产品,而且还要使用产品。当然,如果产品在创建者内部使用,那么工厂方法就是为了完善创建者,从而可以使用创建者。另外创建者本身是不能更换所生产产品的。
优点
- 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理
- 当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品组
- 增加新的产品更加容易,抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码
缺点
- 当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改
- 增加了系统的抽象性和理解难度
示例
抽象工厂模式的主要角色如下:
- 抽象工厂:提供了创建产品的接口,它包含多个创建产品的方法
newProduct()
,可以创建多个不同等级的产品。 - 具体工厂:主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
- 抽象产品:定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
- 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。
类图如下所示:
代码示例:
// 抽象产品A接口
interface AbstractProductA {}
// 抽象产品B接口
interface AbstractProductB {}
// 抽象工厂接口
interface AbstractFactory {
createProductA() : AbstractProductA;
createProductB() : AbstractProductB;
}
// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {
constructor() {}
public createProductA() : AbstractProductA {
return new ConcreteProductA1();
}
public createProductB() : AbstractProductB {
return new ConcreteProductB1();
}
}
// 具体工厂2
class ConcreteFactory2 implements AbstractFactory {
constructor() {}
public createProductA() : AbstractProductA {
return new ConcreteProductA2();
}
public createProductB() : AbstractProductB {
return new ConcreteProductB2();
}
}
// 具体产品A1
class ConcreteProductA1 implements AbstractProductA {}
// 具体产品A2
class ConcreteProductA2 implements AbstractProductA {}
// 具体产品B1
class ConcreteProductB1 implements AbstractProductB {}
// 具体产品B2
class ConcreteProductB2 implements AbstractProductA {}
// 使用
const factory1 : AbstractFactory = new ConcreteFactory1();
const factory2 : AbstractFactory = new ConcreteFactory2();
const productA1 : AbstractProductA = factory1.createProductA();
const productA2 : AbstractProductA = factory2.createProductA();
const productB1 : AbstractProductB = factory1.createProductB();
const productB2 : AbstractProductB = factory2.createProductB();
抽象工厂与工厂方法不同
- 抽象工程关键在于产品之间的抽象关系,所以至少要两个产品;工厂方法在于生成产品,不关注产品间的关系,所以可以只生成一个产品。
- 抽象工厂中客户端把产品的抽象关系理清楚,在最终使用的时候,一般使用客户端,产品之间的关系是被封装固定的;而工厂方法是在最终使用的时候,使用产品本身。
- 抽象工厂的工厂是类;工厂方法的工厂是方法。
抽象工厂的工厂类就做一件事情生产产品。生产的产品给客户端使用,绝不给自己用。工厂方法生产产品,可以给系统用,可以给客户端用,也可以自己这个类使用。自己这个类除了这个工厂方法外,还能有其他功能性的方法。
给工厂方法模式加一个客户端,除了客户端都不用这个创建者。这个时候创建者就是工厂类了。然而抽象工厂模式中,在客户端内部编程时候,就可以把工厂类当作创建者。
总结
抽象工厂模式的扩展有一定的开闭原则
倾斜性,当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码,满足开闭原则。当产品族中需要增加一个新种类的产品时,则所有的工厂类都需要进行修改,不满足开闭原则。另一方面,当系统中只存在一个等级结构的产品时,抽象工厂模式将退化到工厂方法模式。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。