一. 简述
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
比如每个抽象产品角色都有两个具体产品。抽象工厂模式提供两个具体工厂角色,分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。
属于创建型模式。
工厂方法模式 vs 抽象工厂模式
抽象工厂模式是工厂方法模式的升级版本,他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
二. 组成
- 抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
- 具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
- 抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
- 具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
三. UML类图
四. 基本代码
//两种抽象产品:水果、蔬菜
public interface Fruit{}
public interface Veggie{}
//四种具体产品:北方水果,热带水果,北方蔬菜,热带蔬菜
// Northern Fruit
public class NorthernFruit implements Fruit{
private String name;
public NorthernFruit(String name)
{}
public String getName(){
return name;
}
public void setName(String name){
this. name = name;
}
}
// TropicalFruit
public class TropicalFruit implements Fruit{
private String name;
public TropicalFruit(String name)
{}
public String getName(){
return name;
}
public void setName(String name){
this. name = name;
}
}
// NorthernVeggie
public class NorthernVeggie implements Veggie{
private String name;
public NorthernVeggie(String name)
{}
public String getName(){
return name;
}
public void setName(String name){
this. name = name;
}
}
//TropicalVeggie
public class TropicalVeggie implements Veggie{
private String name;
public TropicalVeggie(String name)
{}
public String getName(){
return name;
}
public void setName(String name){
this. name = name;
}
}
//抽象工厂角色
public interface Gardener{
public Fruit createFruit(String name);
public Veggie createVeggie(String name);
}
//具体工厂角色:北方工厂,热带角色
public class NorthernGardener implements Gardener{
public Fruit createFruit(String name){
return new NorthernFruit(name);
}
public Veggie createVeggie(String name){
return new NorthernVeggie(name);
}
}
public class TropicalGardener implements Gardener{
public Fruit createFruit(String name){
return new TropicalFruit(name);
}
public Veggie createVeggie(String name){
return new TropicalVeggie(name);
}
}
五. 优缺点
优点:
- 易于交换产品系列,由于具体工厂类在一个应用中只需在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。
- 让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
缺点:
- 产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。
六. 应用场景
当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。
七. 注意事项
无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。
所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。