意图:
为创建相关的或者相互依赖的对象配置一个借口而不指定他们具体的类。
别名:
Kit
理解:
抽象工厂是一种创建型的模式,它为我们创建对象提供了有效地方法,我们不用直接new对象而是可以为创建对象配置一个接口,该接口定义了如何创建对象的方法。我们还知道抽象工厂创建的对象是一个系列的或者是一族的。该模式的最大特点就是将它的具体创建的任务交给了他的子类也就是具体的类,因此我们将创建对象的时间延迟到了它的子类。我们知道,在设计模式(GOF)的书里说了设计模式是为有一定面向对象基础的开发人员准备的。所以我们都应改知道类和类型之间的区别,在现在的编程语言里接口是最为抽象的数据结构,因此我们将我们的抽象工厂里的AbstractFactoy定义成接口也是很自然的。一个这样的工厂可以创建一族产品是什么意思呢?也就是说这一类产品都有相同的父类或者父接口。在这里我不想重复GOF里面的话关于这些对象之间的协作和结果以及带来的影响等等,这些在《Design Patterns Elements of Resable Object-Oriented Software》本书里可以看到。下面我想用C#实现这个模式来供大家参考。
<!----><v:shapetype o:spt="75" coordsize="21600,21600" filled="f" stroked="f" id="_x0000_t75" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" o:connecttype="rect" gradientshapeok="t"></v:path><!----><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype>
通过我们的面向对象的知识我们知道一个父类可以标识一个子类的对象,这也是理解这里的关键,我们在程序里将会用一个抽象类的对象表示一个子类的对象。如上图所示,我们现在有我们有一个 IabstractFactoy 的接口,该接口的职责就是实现创建对象的工作,我们再有两个具体的工厂 ConcreteFactory1 和 ConcreteFactory2 他们就是具体实现接口中的函数他们实现了这两个方法,当然在具体的应用中可能没有两个具体的工厂,在 GOF 的书中说过在很多情况下我们并没有工厂的抽象接口,大多数情况都是直接使用具体工厂来实现的,在这里我想力图完整的描述书中的结构所以实现也是一样的。好了下面就是我的代码,这段代码显示了我们是怎么在 C# 中实现 AbstractFactory 的。我用一个 WinForm 来测试结构。实现代码:
using System;<o:p></o:p>
<o:p> </o:p>
namespace AbstractFactory_Me<o:p></o:p>
{<o:p></o:p>
public interface IAbstractFactory{<o:p></o:p>
IAbstractProductA CreateProductA();<o:p></o:p>
IAbstractProductB CreateProductB();<o:p></o:p>
}<o:p></o:p>
<o:p> </o:p>
public interface IAbstractProductA{<o:p></o:p>
string ShowSelf();<o:p></o:p>
string ShowOther(IAbstractProductB b);<o:p></o:p>
}<o:p></o:p>
public class ProductA1 : IAbstractProductA{<o:p></o:p>
public ProductA1(){}<o:p></o:p>
public string ShowSelf(){<o:p></o:p>
return this.ToString();<o:p></o:p>
}<o:p></o:p>
public string ShowOther(IAbstractProductB b){<o:p></o:p>
return b.ToString();<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
public class ProductA2 : IAbstractProductA{<o:p></o:p>
public ProductA2(){}<o:p></o:p>
public string ShowSelf(){<o:p></o:p>
return this.ToString();<o:p></o:p>
}<o:p></o:p>
public string ShowOther(IAbstractProductB b){<o:p></o:p>
return b.ToString();<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
<o:p> </o:p>
public interface IAbstractProductB{<o:p></o:p>
string ShowSelf();<o:p></o:p>
string ShowOther(IAbstractProductA a);<o:p></o:p>
}<o:p></o:p>
public class ProductB1 : IAbstractProductB{<o:p></o:p>
public string ShowSelf(){<o:p></o:p>
return this.ToString();<o:p></o:p>
}<o:p></o:p>
public string ShowOther(IAbstractProductA a){<o:p></o:p>
return a.ToString();<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
public class ProductB2 : IAbstractProductB{<o:p></o:p>
public string ShowSelf(){<o:p></o:p>
return this.ToString();<o:p></o:p>
}<o:p></o:p>
public string ShowOther(IAbstractProductA a){<o:p></o:p>
return a.ToString();<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
<o:p> </o:p>
public class ConcreteFactory1 : IAbstractFactory{<o:p></o:p>
<o:p> </o:p>
public IAbstractProductA CreateProductA(){<o:p></o:p>
return new ProductA1();<o:p></o:p>
}<o:p></o:p>
<o:p> </o:p>
public IAbstractProductB CreateProductB(){<o:p></o:p>
return new ProductB1();<o:p></o:p>
}<o:p></o:p>
<o:p> </o:p>
}<o:p></o:p>
<o:p> </o:p>
public class ConcreteFactory2 : IAbstractFactory{<o:p></o:p>
public IAbstractProductA CreateProductA(){<o:p></o:p>
return new ProductA2();<o:p></o:p>
}<o:p></o:p>
public IAbstractProductB CreateProductB(){<o:p></o:p>
return new ProductB2();<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
public class Client{<o:p></o:p>
public void run(){<o:p></o:p>
IAbstractFactory factory1 = new ConcreteFactory1();<o:p></o:p>
IAbstractProductA a = factory1.CreateProductA();<o:p></o:p>
a.ShowSelf();<o:p></o:p>
IAbstractProductB b = factory1.CreateProductB();<o:p></o:p>
b.ShowSelf();<o:p></o:p>
b.ShowOther(a);<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
我们在测试的 WinForm 里面放了一个 richTextBox1 实例,他用来显示结构。 <o:p></o:p>private void Form1_Load(object sender, System.EventArgs e) {<o:p></o:p>
this.richTextBox1.Clear();<o:p></o:p>
IAbstractFactory factory1 = new ConcreteFactory1();<o:p></o:p>
IAbstractProductA a = factory1.CreateProductA();<o:p></o:p>
IAbstractProductB b = factory1.CreateProductB();<o:p></o:p>
<o:p> </o:p>
this.richTextBox1.AppendText(a.ShowSelf()+"\n");<o:p></o:p>
this.richTextBox1.AppendText(b.ShowSelf()+"\n");<o:p></o:p>
this.richTextBox1.AppendText(b.ShowOther(a)+"\n");<o:p></o:p>
this.richTextBox1.AppendText(a.ShowOther(b)+"\n\n\n");<o:p></o:p>
<o:p> </o:p>
this.richTextBox1.AppendText(a.GetType().ToString()+"\n");<o:p></o:p>
this.richTextBox1.AppendText(b.GetType().ToString()+"\n");<o:p></o:p>
<o:p> </o:p>
}
为了清楚的说明问题我们在生成的对象中使用了 ShowSelf 和 ShowOther 的方法用来显示自己和另外一个对象。
GOF书中的例子用C#实现的源码:
using System;<o:p></o:p>
<o:p> </o:p>
namespace AbstractFactory_Maze{<o:p></o:p>
using Maze;<o:p></o:p>
<o:p> </o:p>
public interface AbstractFactory{<o:p></o:p>
MazeClass MakeMaze();<o:p></o:p>
Wall MakeWall();<o:p></o:p>
Room MakeRoom(int n);<o:p></o:p>
Door MakeDoor(Room oneRoom,Room otherRoom);<o:p></o:p>
}<o:p></o:p>
<o:p> </o:p>
public class MazeFactory : AbstractFactory{<o:p></o:p>
public MazeClass MakeMaze(){<o:p></o:p>
return new MazeClass();<o:p></o:p>
}<o:p></o:p>
public Wall MakeWall(){<o:p></o:p>
return new Wall();<o:p></o:p>
}<o:p></o:p>
public Room MakeRoom(int n){<o:p></o:p>
return new Room(n);<o:p></o:p>
}<o:p></o:p>
public Door MakeDoor(Room oneRoom,Room otherRoom){<o:p></o:p>
return new Door(oneRoom,otherRoom);<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
<o:p> </o:p>
// this is a client<o:p></o:p>
public class MazeGame{<o:p></o:p>
public MazeClass MazeCreate(AbstractFactory factory){<o:p></o:p>
MazeClass aMaze = factory.MakeMaze();<o:p></o:p>
Room r1 = factory.MakeRoom(1);<o:p></o:p>
Room r2 = factory.MakeRoom(2);<o:p></o:p>
Door aDoor = factory.MakeDoor(r1,r2);<o:p></o:p>
<o:p> </o:p>