//水果類,它是一個抽象產(chǎn)品 TFruit = Class(TObject) ... end; //蘋果類,水果類的具體化 TApple = class(TFruit) ... end; function Factory(): TFruit; var f:TFruit; begin //精髓就是這條語句了,明明創(chuàng)建了TApple對象, //卻將他賦值給TFruit類型的變量 //其實這樣做好處大大的,后面就體會到了 f:=TApple.Create(); result:=f; end |
//我們用一個小果園來說明什么是簡單工廠 //這個果園里有葡萄、蘋果和草莓三種水果 //所有的水果都有生長、耕作和收獲三個步驟 //果園的任務就是讓我們得到葡萄、蘋果和草莓這三種水果對象 //我們利用得到的對象可以完成水果生長、耕作和收獲三個步驟 //果園就是我們所說的簡單工廠(Factory) //而葡萄、蘋果和草莓這三種水果就是工廠里的產(chǎn)品 (Pruduct) //完成產(chǎn)品的過程稱之為外部使用者(Produce) //使用簡單工廠的好處是: //1、充分利用了多態(tài)性 //不管你種什么,果園返回的對象并不是具體的葡萄、蘋果或者草莓 //而是返回一個他們的抽象對象 -- 水果(IFruit) //2、充分利用了封裝性 //內(nèi)部產(chǎn)品發(fā)生變化時外部使用者不會受到影響 //他的缺點是: //如果增加了新的產(chǎn)品,就必須得修改工廠(Factory) |
//SimpleFactory.pas 定義簡單工廠的單元文件 //代碼如下========== unit SimpleFactory; interface uses SysUtils; type //水果類,它是一個抽象產(chǎn)品 //僅僅聲明了所有對象共有的接口,并不實現(xiàn)他們 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 是一個靜態(tài)函數(shù),可以直接使用 //2、注意返回值,他返回的是最抽象的產(chǎn)品 IFruit 水果類 //3、注意他有一個參數(shù),來告訴工廠創(chuàng)建哪一種水果 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:=‘葡萄已經(jīng)種好了......‘; end; { ********** TApple ********** } function TApple.Grow: string; begin result:=‘蘋果正在生長......‘; end; function TApple.Harvest: string; begin result:=‘蘋果可以收獲了......‘; end; function TApple.Plant: string; begin result:=‘蘋果已經(jīng)種好了......‘; end; { ********** TStrawberry ********** } function TStrawberry.Grow: string; begin result:=‘草莓正在生長......‘; end; function TStrawberry.Harvest: string; begin result:=‘草莓可以收獲了......‘; end; function TStrawberry.Plant: string; begin result:=‘草莓已經(jīng)種好了......‘; end; { ********** TFruitGardener ********** } class function TFruitGardener.Factory(whichFruit:string): IFruit; begin //精髓就是這條語句了 result:= TApple.Create() //不明白趕緊去復習復習什么是多態(tài)性 if(LowerCase(whichFruit)=‘a(chǎn)pple‘)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 ********** } //這就是生產(chǎn)過程 //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(‘a(chǎn)pple‘); 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. |
工廠模式的目的就是,把創(chuàng)建對象的責任和使用對象的責任分開,工廠負責統(tǒng)一創(chuàng)建具體產(chǎn)品(蘋果、葡萄和草莓),然后再把這些產(chǎn)品轉(zhuǎn)化為他們的抽象產(chǎn)品(水果)返回給外部使用者,作為使用者關心的僅僅是抽象產(chǎn)品預留的接口,而不關心他們是怎么創(chuàng)建的。這樣,即使因為某些原因?qū)е聞?chuàng)建產(chǎn)品的過程發(fā)生變化,也不會影響到外部使用者,在一定程度上保證了程序的可維護性。
如果把具體產(chǎn)品類(TApple、TFrabe、TStrawberry)暴露到外部,如果內(nèi)部的代碼發(fā)生了變動,外部也會受到影響,工廠就失去了他的意義。