抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。当要返回一系列相关类种的某一个,而每个类都能根据需要返回不同的对象时,可以使用这种模式。换句话说,抽象工厂是一个工厂对象,它能返回一系列相关类中的一个类,可以使用简单工厂决定返回哪个类。
想想我们一直用的例子人的进化。
人的种族大体分为黄种人,白种人,黑种人。
如果我们遇到这样的一个问题,我们需要进一步细化:
亚洲的黄种人进化成了什么?
亚洲的白种人进化成了什么?
亚洲的黑种人进化成了什么?
非洲的黄种人进化成了什么?
非洲的白种人进化成了什么?
非洲的黑种人进化成了什么?
等等。。。。
考虑到程序的系列(以洲分类)的可扩展性,及我们以后可能需要把世界的七大洲的所有的人都来个细化,这个情况下我们可能需要考虑抽象工厂模式了。
抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的,这里为Evolution类。
具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的,这里为EvolutionInAsia,EvolutionInAfica,EvolutionInEurope类。
抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口,这里为YellowPeron,BlackPerson,WirtePerson以及他们的接口Perosn。
具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑,这里为YellowPersonInAsia,YellowPersonInAfica,YellowPersonInEurope等等。
程序代码(C#):
namespace AbstractFactory
{
/// <summary>
///============== Program Description==============
///Name:AbstractFactory.cs
///Objective:AbstractFactory
///Date:2006-04-24
///Written By coffee.liu
///================================================
/// </summary>
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
Console.WriteLine("In Asia");
Evolution AEv=new EvolutionInAsia();
Client AC=new Client(AEv);
AC.Say();
////////////
Console.WriteLine("In Asfica");
Evolution AFEv=new EvolutionInAfrica();
Client AFC=new Client(AFEv);
AFC.Say();
///////////
Console.WriteLine("In Europe");
Evolution EEv=new EvolutionInEurope();
Client EC=new Client(EEv);
EC.Say();
}
}
public interface Person
{
void GetInfo();
void Say();
}
public class YellowPerson:Person
{
protected string sex,race;
public YellowPerson()
{
sex="Man";
race="Yellow";
}
public YellowPerson(string Ysex)
{
sex=Ysex;
race="Yellow";
}
public virtual void GetInfo()
{
Console.WriteLine("the "+race+" Person Info:"+sex);
}
public virtual void Say()
{
Console.WriteLine("I am a Yellow Baby");
}
}
//中国人
public class YellowPersonInAsia:YellowPerson
{
public override void Say(){
Console.WriteLine("YellowPerson:I am a Chinese中国人");
}
}
//没有进化成功
public class YellowPersonInAfica:YellowPerson
{
public override void Say()
{
Console.WriteLine("YellowPerson:I am aNo evolutioned没有进化成功");
}
}
//伊斯兰人
public class YellowPersonInEurope:YellowPerson
{
public override void Say()
{
Console.WriteLine("YellowPerson:I am a Yi Silan伊斯兰人");
}
}
public class BlackPerson:Person
{
protected string sex,race;
public BlackPerson()
{
sex="Man";
race="Black";
}
public BlackPerson(string Bsex)
{
sex=Bsex;
race="Black";
}
public virtual void GetInfo()
{
Console.WriteLine("the "+race+" Person Info:"+sex);
}
public virtual void Say()
{
Console.WriteLine("I am a Black Baby");
}
}
//黑猩猩
public class BlackPersonInAsia:BlackPerson
{
public override void Say()
{
Console.WriteLine("BlackPerson:I am a Chimpanzee,I like bananana..黑猩猩");
}
}
//非洲人
public class BlackPersonInAfica:BlackPerson
{
public override void Say()
{
Console.WriteLine("BlackPerson:I am a African 非洲人");
}
}
//猴子
public class BlackPersonInEurope:BlackPerson
{
public override void Say()
{
Console.WriteLine("BlackPerson:I am a Monkey,I like bananana..猴子");
}
}
public class WritePerson:Person
{
protected string sex,race;
public WritePerson()
{
sex="Man";
race="Write";
}
public WritePerson(string Wsex)
{
sex=Wsex;
race="Write";
}
public virtual void GetInfo()
{
Console.WriteLine("the "+race+" Person Info:"+sex);
}
public virtual void Say()
{
Console.WriteLine("I am a Write Baby");
}
}
//猿
public class WritePersonInAsia:WritePerson
{
public override void Say()
{
Console.WriteLine("WritePerson:I am a Ape,I like bananana..猿");
}
}
//跳蚤
public class WritePersonInAfica:WritePerson
{
public override void Say()
{
Console.WriteLine("WritePerson:I am a Flea,I like ..跳蚤");
}
}
//高加索人
public class WritePersonInEurope:WritePerson
{
public override void Say()
{
Console.WriteLine("WritePerson:I am a Caucasus.高加索人");
}
}
public abstract class Evolution
{
public abstract Person evolution();
public abstract YellowPerson evlutionToyellow();
public abstract BlackPerson evlutionToblack();
public abstract WritePerson evlutionTowrite();
}
public class EvolutionInAsia:Evolution
{
public override Person evolution()
{
return null;
}
public override YellowPerson evlutionToyellow()
{
return new YellowPersonInAsia();
}
public override WritePerson evlutionTowrite()
{
return new WritePersonInAsia();
}
public override BlackPerson evlutionToblack()
{
return new BlackPersonInAsia();
}
}
public class EvolutionInAfrica:Evolution{
public override Person evolution()
{
return null;
}
public override YellowPerson evlutionToyellow()
{
return new YellowPersonInAfica();
}
public override WritePerson evlutionTowrite()
{
return new WritePersonInAfica();
}
public override BlackPerson evlutionToblack()
{
return new BlackPersonInAfica();
}
}
public class EvolutionInEurope:Evolution{
public override Person evolution()
{
return null;
}
public override YellowPerson evlutionToyellow()
{
return new YellowPersonInEurope();
}
public override WritePerson evlutionTowrite()
{
return new WritePersonInEurope();
}
public override BlackPerson evlutionToblack()
{
return new BlackPersonInEurope();
}
}
public class EvolutionToYellow:Evolution
{
public override Person evolution()
{
return new YellowPerson();
}
public override YellowPerson evlutionToyellow()
{
return null;
}
public override WritePerson evlutionTowrite()
{
return null;
}
public override BlackPerson evlutionToblack()
{
return null;
}
}
public class EvolutionToBlack:Evolution
{
public override Person evolution()
{
return new BlackPerson();
}
public override YellowPerson evlutionToyellow()
{
return null;
}
public override WritePerson evlutionTowrite()
{
return null;
}
public override BlackPerson evlutionToblack()
{
return null;
}
}
public class EvolutionToWrite:Evolution
{
public override Person evolution()
{
return new WritePerson();
}
public override YellowPerson evlutionToyellow()
{
return null;
}
public override WritePerson evlutionTowrite()
{
return null;
}
public override BlackPerson evlutionToblack()
{
return null;
}
}
public class Client
{
private YellowPerson YP;
private BlackPerson BP;
private WritePerson WP;
public Client(Evolution ev){
YP=ev.evlutionToyellow();
BP=ev.evlutionToblack();
WP=ev.evlutionTowrite();
}
public void Say(){
YP.Say();
BP.Say();
WP.Say();
}
}
}
(Pascal代码过后给出,以后我每次都先给出C#代码,过一段时间再给出Pascal代码,毕竟Delphi还不是完全oo的,作起来呵呵精力消耗很大)
我们再看一个Pascal的例子:在这个例子中我们使用抽象工厂模式生成两种不同系列的按钮
2 //============== Program Description==============
3 //Name:AbstractPattom.dpr
4 //Objective:AbstractPattom
5 //Date:2006-04-27
6 //Written By coffee.liu
7 //================================================
8interface
9
10uses
11 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
12 Dialogs,StdCtrls;
13
14type
15 TAbstractButtonFactory=class
16 class function CreateBigBtn():Tbutton;virtual;abstract;
17 class function CreateSamllBtn():TButton;virtual;abstract;
18 end;
19 TButtonFactoryA=class(TAbstractButtonFactory)
20 public
21 class function CreateBigBtn():Tbutton;override;
22 class function CreateSamllBtn():TButton;override;
23 end;
24 TButtonFactoryB=class(TAbstractButtonFactory)
25 public
26 class function CreateBigBtn():Tbutton;override;
27 class function CreateSamllBtn():TButton;override;
28 end;
29 TForm1 = class(TForm)
30
31 procedure FormCreate(Sender: TObject);
32 private
33 { Private declarations }
34 public
35 { Public declarations }
36 end;
37
38var
39 Form1: TForm1;
40
41implementation
42
43{$R *.dfm}
44
45{ TButtonFactoryA }
46
47class function TButtonFactoryA.CreateBigBtn: Tbutton;
48begin
49 result:=TButton.Create(nil);
50 result.Hint:='I am created from TButtonFactoryA';
51 result.ShowHint:=true;
52 result.Height:=40;
53 Result.Width:=40;
54end;
55
56class function TButtonFactoryA.CreateSamllBtn: TButton;
57begin
58 result:=TButton.Create(nil);
59 result.Hint:='I am created from TButtonFactoryA';
60 result.ShowHint:=true;
61 result.Height:=20;
62 Result.Width:=20;
63end;
64
65{ TButtonFactoryB }
66
67class function TButtonFactoryB.CreateBigBtn: Tbutton;
68begin
69 result:=TButton.Create(nil);
70 result.Hint:='I am created from TButtonFactoryB';
71 result.ShowHint:=true;
72 result.Height:=50;
73 Result.Width:=50;
74end;
75
76class function TButtonFactoryB.CreateSamllBtn: TButton;
77begin
78 result:=TButton.Create(nil);
79 result.Hint:='I am created from TButtonFactoryB';
80 result.ShowHint:=true;
81 result.Height:=25;
82 Result.Width:=25;
83end;
84
85procedure TForm1.FormCreate(Sender: TObject);
86
87var
88AA,BB:TAbstractButtonFactory;
89ButtonA1,ButtonA2,ButtonB1,ButtonB2:TButton;
90begin
91 AA:=TButtonFactoryA.Create;
92 BB:=TButtonFactoryB.Create;
93 ButtonA1:=AA.CreateBigBtn;
94 ButtonA1.Parent:=Form1;
95 ButtonA1.Caption:='BA';
96
97 ButtonA2:=AA.CreateSamllBtn;
98 ButtonA2.Parent:=Form1;
99 ButtonA2.Caption:='SA';
100 ButtonA2.Left:=60;
101
102 ButtonB1:=BB.CreateBigBtn;
103 ButtonB1.Parent:=Form1;
104 ButtonB1.Caption:='BB';
105 ButtonB1.Left:=100;
106
107 ButtonB2:=BB.CreateSamllBtn;
108 ButtonB2.Parent:=Form1;
109 ButtonB2.Caption:='SB';
110 ButtonB2.Left:=160;
111
112end;
113
114end.
115
抽象工厂的一个主要的目的是它能隔离要生成的具体类,这些类的实际类名隐藏在工厂里,在客户端根本不需要知道。由于类的隔离,可以自由改动或交换这些生成类系列,此外由于只生成一类具体的类,系统会避免读者误用不同生成系列中的类,但是添加新的类系列要费一些心思,因为读者要定义一些新的,无二义性的条件使工厂能够返回性的类系列。