用 Delphi 学设计模式(一) 之 简单工厂篇

学习设计模式要对面向对象的程序设计有一定的理解,特别是多态性 ,如果能看懂下面的例子就没问题了,呵呵!


//水果类,它是一个抽象产品 
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)暴露到外部,如果内部的代码发生了变动,外部也会受到影响,工厂就失去了他的意义。

转载于:https://www.cnblogs.com/lzj1981/archive/2013/04/29/3050485.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值