一. 抽象工厂模式概述
抽象工厂模式是工厂模式中最一般、最抽象的一种表现形式,是对工厂方法模式的进一步扩充。工厂方法模式可以对一类产品的建造进行管理,将建造具体产品的建造过程交给到具体的子类中完成。如果需要管理两类及以上产品的建造过程呢?当然很自然的就可以想到可以使用多个工厂方法实现。这样做的问题在于,一是导致工厂过于分散不好管理;二是这几类产品之间如果存在密切的关系,他们的建造过程并不能完全分开,多个建造者之间必然会存在复杂的相互依赖关系。因此,一个更好的方法是:既然这些产品的建造过程是相关的,就把他们集中到一个大的建造工厂中实现。
这是一个要创建的产品的复杂度的问题。如果只是一个汽车轮胎厂,生产的产品只限于轮胎一个产品种类(可能有不同的型号),这是一个典型的工厂方法问题。如果是一个更负责的汽车制造厂,除了生产汽车轮胎外,还生产汽车引擎、车身等其他产品(都可能还有不同型号),这些产品之间又有密切的关系,比如,某种特定种类的汽车由特定种类的轮胎、引擎和车手组成——这个组合是一个密切相关的系列,那么,这就是一个抽象工厂的问题。
GoF这样描述抽象工厂模式的意图:
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
二. 抽象工厂模式实例
有一家汽车制造商,生产两种类型的汽车:商用车和赛车。假定汽车都是由车身和引擎两个部分组成;这样,生产两种汽车的方法很简单:只需要把不同的车身和引擎组装起来就可以了:商用车使用BodyA车身和Benz引擎,而赛车使用BodyB车身和Ferrari引擎。如下图:
程序代码如下:
namespace
AbstractFactory
... {
//车身抽象定义
public abstract class Body
...{
public abstract void Show();
}
//车身A
public class BodyA : Body
...{
public override void Show()
...{
Console.Write("BodyA");
}
}
//车身B
public class BodyB : Body
...{
public override void Show()
...{
Console.Write("BodyB");
}
}
//引擎抽象定义
public abstract class Engine
...{
public abstract void Show();
}
//Benz引擎
public class Benz : Engine
...{
public override void Show()
...{
Console.Write("Benz");
}
}
//Ferrari引擎
public class Ferrari : Engine
...{
public override void Show()
...{
Console.Write("Ferrari");
}
}
//汽车制造厂抽象定义
public abstract class CarFactory
...{
public abstract Body GetBody(); //车身工厂方法
public abstract Engine GetEngine(); //引擎工厂方法
public virtual void Produce()
...{
Console.Write("This is a car with the body of ");
GetBody().Show();
Console.Write(" and the engine of ");
GetEngine().Show();
}
}
//商务车制造厂
public class BusinessCarBranch : CarFactory
...{
public override Body GetBody()
...{
return new BodyA();
}
public override Engine GetEngine()
...{
return new Benz();
}
}
//赛车制造厂
public class SportsCarBranch : CarFactory
...{
public override Body GetBody()
...{
return new BodyB();
}
public override Engine GetEngine()
...{
return new Ferrari();
}
}
//客户端
class Client
...{
static void Main(string[] args)
...{
CarFactory factory = new SportsCarBranch();
factory.Produce();
Console.ReadKey();
}
}
}
... {
//车身抽象定义
public abstract class Body
...{
public abstract void Show();
}
//车身A
public class BodyA : Body
...{
public override void Show()
...{
Console.Write("BodyA");
}
}
//车身B
public class BodyB : Body
...{
public override void Show()
...{
Console.Write("BodyB");
}
}
//引擎抽象定义
public abstract class Engine
...{
public abstract void Show();
}
//Benz引擎
public class Benz : Engine
...{
public override void Show()
...{
Console.Write("Benz");
}
}
//Ferrari引擎
public class Ferrari : Engine
...{
public override void Show()
...{
Console.Write("Ferrari");
}
}
//汽车制造厂抽象定义
public abstract class CarFactory
...{
public abstract Body GetBody(); //车身工厂方法
public abstract Engine GetEngine(); //引擎工厂方法
public virtual void Produce()
...{
Console.Write("This is a car with the body of ");
GetBody().Show();
Console.Write(" and the engine of ");
GetEngine().Show();
}
}
//商务车制造厂
public class BusinessCarBranch : CarFactory
...{
public override Body GetBody()
...{
return new BodyA();
}
public override Engine GetEngine()
...{
return new Benz();
}
}
//赛车制造厂
public class SportsCarBranch : CarFactory
...{
public override Body GetBody()
...{
return new BodyB();
}
public override Engine GetEngine()
...{
return new Ferrari();
}
}
//客户端
class Client
...{
static void Main(string[] args)
...{
CarFactory factory = new SportsCarBranch();
factory.Produce();
Console.ReadKey();
}
}
}
三.抽象工厂模式角色和结构
抽象工厂模式的一般结构如下图所示:
-
AbstractProductA/B:抽象产品角色,定义一类产品的抽象接口。
-
ConcreteProductA1/A2/B1/B2:具体产品角色,具体的由工厂所生产的产品,实现了相应的抽象产品接口。
-
AbstractFactory:抽象工厂角色,定义工厂生产产品的抽象方法。
-
ConcreteFactory1/2:具体工厂角色,实现抽象工厂定义的方法,负责具体产品的生产。
-
Client/Caller:客户端/调用程序,只依赖于抽象工厂及抽象产品定义。
四. 抽象工厂模式总结
抽象工厂模式是最一般、最抽象的工厂方法,对产品的创建细节进行了最大限度的封装,完全隔离了客户对具体产品的依赖关系。客户可以在完全对产品创建细节不知情的情况下通过更换具体工厂实现产品的更替。
抽象工厂模式对于产品系列的增加具有很好的支持。比如,在上面的例子中,如果想增加一个新的产品系列,比如工业用车,只需要添加工业车制造工厂、具体的工业车部件(车身、引擎)就可以了。这是对OCP原则的忠实体现。
抽象工厂模式适用于以下场景(摘于GoF《设计模式》):
-
一个系统要独立于它的产品的创建、组合和表示。
-
一个系统要由多个产品系列中的一个来配置。(如上的两种汽车)
-
当你要强调一系列相关的产品对象的设计一便进行联合使用时。(多种部件构成汽车)
-
提供一个类库,而只想显示接口