设计模式之抽象工厂

抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。

为了方便引进抽象工厂模式,引进一个新概念:产品族(Product Family)。所谓产品族,是指位于不同产品等级结构,功能相关联的产品组成的家族。如图:


图中一共有四个产品族,分布于三个不同的产品等级结构中。只要指明一个产品所处的产品族以及它所属的等级结构,就可以唯一的确定这个产品。

引进抽象工厂模式

所谓的抽象工厂是指一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象。如果用图来描述的话,如下图:


结构图:


图中描述的东西用产品族描述如下:


抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。

具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。

抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。

具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。

程序举例:

微型计算机配件,这个系统所需要的产品族有两个,一个系列是PC系列,另一个系列是MAC系列。
产品等级结构也有两个,一个是RAM,一个是CPU。
//两个抽象产品
public interface Cpu
{
}
public interface Ram
{
}
//四个具体产品
public class PcCpu implements Cpu
{
}
public class MacCpu implements Cpu
{
}
public class PcRam implements Ram
{
}
public class MacRam implements Ram
{
}
//抽象工厂角色
public interface ComputerProducer
{
Cpu createCpu();
Ram createRam();
}
//两个具体工厂角色
public class PcProducer implements ComputerProducer
{
public Cpu createCpu()
{
return new PcCpu();
}
public Ram createRam()
{
return new PcRam();
}
}
public class MacProducer implements ComputerProducer
{
public Cpu createCpu()
{
return new MacCpu();
}
public Ram createRam()
{
return new MacRam();
}
}
一般情况下,有多少个抽象产品,就有多少个工厂方法。(比如再增加一个PC与MAC不同的其他计算机配件,例如显卡)。


使用场景:

1.系统不依赖于产品类实例如何被创建,组合和表达的细节。
2.系统的产品有多于一个的产品族,而系统只消费其中某一族的产品(抽象工厂模式的原始用意Unix&Windows)
Button--->UnixButton/WinButton
Text----->UnixText/WinText
Unix产品族和Windows产品族,不会同时使用。
Factory--->UnixFactory/WinFactory
3.同属于同一个产品族是在一起使用的。这一约束必须在系统的设计中体现出来。
4.系统提供一个产品类的库,所有产品以同样的接口出现,从而使 客户端不依赖于实现。
与其他设计模式的关系

单例模式:具体工厂类可以设计成单例类,一个单例类只有一个实例,它自己向外界提供自己唯一的实例。很显然,在农场系统中,只需要NorthernGardener和TropicalGardener的一个实例就可以了。而在计算机生产的例子中,PcProducer和RamProducer也分别只需要一个实例。
工厂的工厂:工厂角色与抽象产品角色合并( 简单工厂模式java.util.DateFormat),在抽象工厂模式中,抽象工厂类可以有静态方法,这个方法根据参数的值,返回对应的具体工厂类实例,但是其返回值类型是抽象工厂类型,这样可以在多态性的保证之下,允许静态工厂方法自行决定哪一个具体工厂符合要求。
//计算机生产抽象工厂角色
abstract public class ComputerProducer
{
public static ComputerProducer getProducer(String which)
{
if (which.equalsIgnoreCase("PC"))
{
return new PcProducer();
}
else if (which.equalsIgnoreCase("Mac"))
{
return new MacProducer();
}
else
{
return null;
}
}
}
工厂的工厂:工厂角色可以和具体产品角色合并(简单工厂模式),在抽象工厂模式中,每一个具体工厂类可以有一个 静态方法,其返回值类型是该具体工厂类自己。
public class MacProducer extends ComputerProducer
{
private static MacProducer producer = new MacProducer();
private MacProducer() {
}
public Cpu createCpu()
{
return new MacCpu();
}
public Ram createRam()
{
return new PcRam();
}
public static MacProducer getInstance()
{
return producer;
}
}
女娲造万物的故事:
神绳(+举绳造物())
阴绳 阳绳
女人 男人
动物
雌性 雄性
在JAVA语言的AWT库中,使用了抽象工厂模式创建分水域不同 操作系统的Peer构件(与本地系统相关的GUI组件)。
优点:

第一,易于交换产品系列,由于具体工厂类,例如IDBFactory factory = new OracleFactory(),在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它之需要改变具体工厂即可使用不同的产品配置。

第二,它让具体的创建实例与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。

总结:

"开放-封闭"原则要求系统对扩展开放,对修改封闭。通过扩展达到增强其功能的目的。对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:

增加产品族:Abstract Factory很好的支持了"开放-封闭"原则。

增加新产品的等级结构:需要修改所有的工厂角色,没有很好支持"开放-封闭"原则。

综合起来,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,而不能为新的产品等级结构的增加提供这样的方便。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值