工厂模式中又分为简单工厂模式、工厂方法模式和抽象工厂模式 。这里给大家介绍的简单工厂模式是其中最简单的一种。
学习设计模式要对面向对象的程序设计有一定的理解,特别是多态性 ,如果能看懂下面的例子就没问题了,呵呵!
//水果类,它是一个抽象产品 TFruit = Class(TObject) ... end; //苹果类,水果类的具体化 TApple = class(TFruit) ... end; function Factory(): TFruit; var f:TFruit; begin //精髓就是这条语句了,明明创建了TApple对象, //却将他赋值给TFruit类型的变量 //其实这样做好处大大的,后面就体会到了 f:=TApple.Create(); result:=f; end |
在例程中我用到了接口 ,不明白得可以把它当成一个比抽象类还抽象的抽象类,说白了把它当成一个类就没错。 下面开始吧。。。。。。。
这是说明:
//我们用一个小果园来说明什么是简单工厂 //这个果园里有葡萄、苹果和草莓三种水果 //所有的水果都有生长、耕作和收获三个步骤 //果园的任务就是让我们得到葡萄、苹果和草莓这三种水果对象 //我们利用得到的对象可以完成水果生长、耕作和收获三个步骤 //果园就是我们所说的简单工厂(Factory) //而葡萄、苹果和草莓这三种水果就是工厂里的产品 (Pruduct) //完成产品的过程称之为外部使用者(Produce) //使用简单工厂的好处是: //1、充分利用了多态性 //不管你种什么,果园返回的对象并不是具体的葡萄、苹果或者草莓 //而是返回一个他们的抽象对象 -- 水果(IFruit) //2、充分利用了封装性 //内部产品发生变化时外部使用者不会受到影响 //他的缺点是: //如果增加了新的产品,就必须得修改工厂(Factory) |
这是定义简单工厂的单元文件源代码:
//SimpleFactory.pas 定义简单工厂的单元文件 //代码如下========== unit SimpleFactory; interface uses SysUtils; type //水果类,它是一个抽象产品 //仅仅声明了所有对象共有的接口,并不实现他们 IFruit = interface(IInterface) function Grow: string; //生长 function Harvest: string; //收获 function Plant: string;//耕作 end; //葡萄类,水果类的具体化 TGrape = class(TInterfacedObject, IFruit) function Grow: string; function Harvest: string; function Plant: string; end; //苹果类,水果类的具体化 TApple = class(TInterfacedObject, IFruit) function Grow: string; function Harvest: string; function Plant: string; end; //草莓类,水果类的具体化 TStrawberry = class(TInterfacedObject, IFruit) function Grow: string; function Harvest: string; function Plant: string; end; //果园类,它就是工厂类,负责给出三种水果的实例 TFruitGardener = class(TObject) public //1、注意 class 关键字,它定义工厂方法 Factory 是一个静态函数,可以直接使用 //2、注意返回值,他返回的是最抽象的产品 IFruit 水果类 //3、注意他有一个参数,来告诉工厂创建哪一种水果 class function Factory(whichFruit:string): IFruit; end; //声明一个异常,这不是重点 NoThisFruitException = class(Exception) end; implementation { ********** TGrape ********** } function TGrape.Grow: string; begin result:=‘葡萄正在生长......‘; end; function TGrape.Harvest: string; begin result:=‘葡萄可以收获了......‘; end; function TGrape.Plant: string; begin result:=‘葡萄已经种好了......‘; end; { ********** TApple ********** } function TApple.Grow: string; begin result:=‘苹果正在生长......‘; end; function TApple.Harvest: string; begin result:=‘苹果可以收获了......‘; end; function TApple.Plant: string; begin result:=‘苹果已经种好了......‘; end; { ********** TStrawberry ********** } function TStrawberry.Grow: string; begin result:=‘草莓正在生长......‘; end; function TStrawberry.Harvest: string; begin result:=‘草莓可以收获了......‘; end; function TStrawberry.Plant: string; begin result:=‘草莓已经种好了......‘; end; { ********** TFruitGardener ********** } class function TFruitGardener.Factory(whichFruit:string): IFruit; begin //精髓就是这条语句了 result:= TApple.Create() //不明白赶紧去复习复习什么是多态性 if(LowerCase(whichFruit)=‘apple‘)then result:=TApple.Create() else if(LowerCase(whichFruit)=‘grape‘)then result:=TGrape.Create() else if(LowerCase(whichFruit)=‘strawberry‘)then result:=TStrawberry.Create() else Raise NoThisFruitException.Create(‘这种水果还没有被种植!‘); end; end. |
窗体界面:
//MainForm.pas 窗体文件,这里说明怎样使用简单工厂 unit MainForm; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,SimpleFactory, StdCtrls; type TForm1 = class(TForm) RadioButton1: TRadioButton; RadioButton2: TRadioButton; RadioButton3: TRadioButton; RadioButton4: TRadioButton; procedure RadioButton1Click(Sender: TObject); procedure RadioButton2Click(Sender: TObject); procedure RadioButton3Click(Sender: TObject); procedure RadioButton4Click(Sender: TObject); public procedure Produce(fruitName:string); end; var Form1: TForm1; implementation { ********** TForm1 ********** } //这就是生产过程 //IFruit 类型的临时变量 f 自己知道种的是哪种水果,有趣吧 //想要什么尽管来种,果园大丰收啦! procedure TForm1.Produce(fruitName:string); var f: IFruit; begin try f:=TFruitGardener.Factory(fruitName); ShowMessage(f.Plant()); ShowMessage(f.Grow()); ShowMessage(f.Harvest()); except on e:NoThisFruitException do Messagedlg(e.Message,mtInformation,[mbOK],0); end; end; {$R *.dfm} procedure TForm1.RadioButton1Click(Sender: TObject); begin Produce(‘apple‘); end; procedure TForm1.RadioButton2Click(Sender: TObject); begin Produce(‘grape‘); end; procedure TForm1.RadioButton3Click(Sender: TObject); begin Produce(‘strawberry‘); end; procedure TForm1.RadioButton4Click(Sender: TObject); begin Produce(‘other‘); end; end. |
工厂模式的目的就是,把创建对象的责任和使用对象的责任分开,工厂负责统一创建具体产品(苹果、葡萄和草莓),然后再把这些产品转化为他们的抽象产品(水果)返回给外部使用者,作为使用者关心的仅仅是抽象产品预留的接口,而不关心他们是怎么创建的。这样,即使因为某些原因导致创建产品的过程发生变化,也不会影响到外部使用者,在一定程度上保证了程序的可维护性。
如果把具体产品类(TApple、TFrabe、TStrawberry)暴露到外部,如果内部的代码发生了变动,外部也会受到影响,工厂就失去了他的意义。