设计模式之抽象工厂

理解抽象工厂模式包括要注意以下几个方面
1. 在工厂方法模式中我们描述了,抽象工厂创建抽象产品的过程,那什么不使用一个工厂类直接创建抽象产品呢?
其实原因很简单:抽象产品角色是由Java 接口或者抽象Java 类实现的,而一个Java 接口或者抽象Java 类是不能实例化的。也就是说,一个工厂类是不能直接创建抽象产品的。
2. 根据里氏代换原则(可详见《java编程思想》),何接收父类型的地方,都应当能够接收子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色 相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例如下图所示。

图5.1.3_1 抽象工厂模式的含义
根据上面的图,我们可以对比一下工厂方法:工厂方法模式中,通过抽象工厂创建的是抽象产品,对于一个良好的工厂方法设计,一个抽象工厂创建的是一个抽象产品角色。因此需要多个抽象工厂,这种效果在实际应用上比较繁锁。
而抽象工厂创建的工作下放到子类,而子类创建的也是产品的具体实类,如果这样,那么工厂类就很好的解决了工厂方法不足的一面。
3. 对于每个抽象产品都有多于一个的具体子类的话,工厂角色怎么知道实例化哪一个子类呢?如下图所示:

 
理解了这三个步骤,就不难理解“抽象工厂”这个名字的来源了。“抽象”来自“抽象产品角色”,而“抽象工厂”就是抽象产品角色的工厂。
 
在抽象工厂中,我们引进“产品族”的概念;如下图(相图)所示:

对于产品族而言,从上图可知,每一个抽象产品具有三个具体产品;每一个具体工厂类对应一个产品族。在上面的相图中加入了具体工厂角色。可以看出,对应于每一个产品族都有一个具体工厂。而每一个具体工厂负责创建属于同一个产品族、但是分属于不同等级结构的产品。
 
抽象工厂模式结构
抽 象工厂模式是对象的创建模式,它是工厂方法模式的进一步推广。假设一个子系统需要一些产品对象,而这些产品又属于一个以上的产品等级结构。那么为了将消费 这些产品对象的责任和创建这些产品对象的责任分割开来,可以引进抽象工厂模式。这样的话,消费产品的一方不需要直接参与产品的创建工作,而只需要向一个公 用的工厂接口请求所需要的产品。下面就以一个示意性的系统为例,说明这个模式的结构。
通过使用抽象工厂模式,可以处理具有相同(或者相似)等级结构的多个产品族中的产品对象创建问题。比如下面就是两个具有相同等级结构的产品族A 和产品等级结构B 的结构图。

图5.1.3_2 产品族
 
上图中,有两个产品族,每一个产品族具有两个具体产品。我们可以使用相图描述上面的结构,其中横坐标表示,每一个抽象产品下面具有的产品个数(2个);纵坐标表示,具有几个抽象产品(2个)。

 
基于以上,在实际应用中,我们不难给出采用抽象工厂模式设计出的系统类图如下所示。

 
从上图可以看出,抽象工厂模式涉及到以下的角色。
1. 抽象工厂( AbstractFactory )角色:担任这个角色的是工厂方法模式的核心,它是与应用系统的商业逻辑无关的。通常使用Java 接口或者抽象Java 类实现,而所有的具体工厂类必须实现这个Java 接口或继承这个抽象Java 类。
2. 具体工厂类( Conrete Factory )角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。通常使用具体Java 类实现这个角色。
   3. 抽象产品( Abstract Product )角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。通常使用Java 接口或者抽象Java 类实现这一角色。
4. 具体产品( Concrete Product )角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。通常使用具体Java 类实现这个角色。
 
上面的结构图,代码部分我就不陈出来了,大家可以见“工厂方法”一节,其中要注意的是ConcreteCreator1两个方法中,返回的是ProductA1和ProductB1。
 
抽象工厂的使用情况
(1)一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节。这对于所有形态的工厂模式都是重要的;
(2) 这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品;(上面这一条叫做抽象工厂模式的原始用意,在现代的应用中,抽象工厂模式的使用范围已经大大扩大了,不再要求系统只能消费某一个产品族了;因此读者可以不理会前面所提到的原始用意。)
(3)同属于同一个产品族的产品是在一起使用的,这一约束必须要在系统的设计中体现出来;
(4)系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
仔细思考一下,很多人都会问这样一个问题:为什么在第二条中说“系统只消费其中某一族的产品”呢?这实际上与抽象工厂模式的起源有关。
 
我们在工厂方法中,作了应用示例,现在放到抽象工厂中,设计图如下所示:

 
相信大家通过“简单工厂”一节,以及“工厂方法”一节,对上面的图难很快的编写出示例源码,间于篇幅,我就不再例举源码。
 
抽象工厂中的增加
1. 在产品等级结构的数目不变的情况下,增加新的产品族,就意味着在每一个产品等级结构中增加一个(或者多个)新的具体(或者抽象和具体)产品角色。
由于工厂等级结构是与产品等级结构平行的登记机构,因此,当产品等级结构有所调整时,需要将工厂等级结构做相应的调整。现在产品等级结构中出现了新的元素,因此,需要向工厂等级结构中加入相应的新元素就可以了。
换言之,设计师只需要向系统中加入新的具体工厂类就可以了,没有必要修改已有的工厂角色或者产品角色。 因此,在系统中的产品族增加时,抽象工厂模式是支持“开 - 闭”原则的。
2. 在产品族的数目不变的情况下,增加新的产品等级结构。换言之,所有的产品等级结构中的产品数目不会改变,但是现在多出一个与现有的产品等级结构平行的新的产品等级结构。
要做到这一点,就需要修改所有的工厂角色,给每一个工厂类都增加一个新的工厂方法,而这显然是违背“开–闭”原则的。换言之, 对于产品等级结构的增加,抽象工厂模式是不支持“开–闭”原则的
 
综合起来,我们可以知道,在已有的抽象产品中添加其具体产品,支持“开—闭原则”,然而在添加其抽象产品时,确不支持“开—闭”原则。抽象工厂模式以一种 倾斜的方式支持增加新的 产品 它为新产品族的增加提供方便,而不能为新的产品等级结构的增加提供这样的方便。
 
:
个人认为,在基于抽象工厂的设计中,对于产品族和产品等级的设计与区分是很重要的,这往往对于初学者来说,容易混淆。
对于具体工厂类,应按照相图中的产品族来定义。相图中的横坐标表示的是抽象产品角色。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值