分享
 
 
 

用 Delphi 学设计模式(二) 之 工厂方法篇 (原创)

王朝delphi·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

?

“开闭原则”:一个模块应该易于扩展,免于修改

问题:请考虑上一章的例子中,如果添加一个新的具体水果类“西瓜”需要做哪些工作。

本章完成以下内容:

1、代码用支持中文的 Delphi 2005 编译并通过,并去除了其中一些无关紧要的地方,如异常处理等 ;

2、重新设计一个情景,分别用“简单工厂模式”和“工厂方法模式”两种方法实现,请体会其中的差别 ;

3、在情景中添加一个子类后,请体会“简单工厂模式”和“工厂方法模式”两种方法不同的处理方式;

4、如果不理解什么是接口、多态、静态函数等概念,这里不作解释,请看第一章或找相关资料;

5、本章的情景和上一章差不多,只是把工厂从“果园”变成了“水果小贩”;同样的三种水果:苹果、葡萄、草莓;每种水果都封装了两个逻辑,在和外部“交易”时会用到这两个逻辑。 最后,请重新回顾“开闭原则”

下面开始吧。。。。。。。

这里是简单工厂模式的实现方法,在这种模式中:

1、一个小贩要负责所有三种水果的交易,这对他来说是很大的挑战噢,不信您看!

2、顾客必须对水果的名字有一个准确地描述,这样水果才会卖给你,这很影响生意呀!

//简单工厂类和水果类单元文件

unit SimpleFactory;

interface

type

接口_水果 = interface(IInterface)

function 提示():string;

function 被评价():string;

end;

类_苹果 = class(TInterfacedObject, 接口_水果)

function 提示():string;

function 被评价():string;

end;

类_葡萄 = class(TInterfacedObject, 接口_水果)

function 提示():string;

function 被评价():string;

end;

类_草莓 = class(TInterfacedObject, 接口_水果)

function 提示():string;

function 被评价():string;

end;

工厂类_小贩 = class(TObject)

public

class function 工厂(水果名:string): 接口_水果;

end;

implementation

{***** 类_苹果 *****}

function 类_苹果.提示():string;

begin

result:='削了皮再吃!';

end;

function 类_苹果.被评价():string;

begin

result:='恩,还不错,挺甜!';

end;

{*****类_葡萄 *****}

function 类_葡萄.提示():string;

begin

result:='别把核咽下去了!';

end;

function 类_葡萄.被评价():string;

begin

result:='没有核呀???';

end;

{***** 类_草莓 *****}

function 类_草莓.提示():string;

begin

result:='别怪我没告诉你,很酸!';

end;

function 类_草莓.被评价():string;

begin

result:='试试?哇,牙快酸掉了!';

end;

{***** 工厂类_小贩 *****}

class function 工厂类_小贩.工厂(水果名:string): 接口_水果;

begin

if(水果名='苹果')then result:=类_苹果.Create()

else if(水果名='葡萄')then result:=类_葡萄.Create()

else if(水果名='草莓')then result:=类_草莓.Create();

end;

end.

//窗体单元文件

unit MainForm;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls,SimpleFactory;

type

TForm1 = class(TForm)

RadioButton1: TRadioButton;

RadioButton2: TRadioButton;

RadioButton3: TRadioButton;

procedure RadioButton3Click(Sender: TObject);

procedure RadioButton2Click(Sender: TObject);

procedure RadioButton1Click(Sender: TObject);

private

procedure 交易(水果名:string);

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.交易(水果名:string);

var

我买的水果: 接口_水果;

begin

我买的水果:=工厂类_小贩.工厂(水果名);

ShowMessage(我买的水果.提示);

ShowMessage(我买的水果.被评价);

end;

procedure TForm1.RadioButton1Click(Sender: TObject);

begin

交易('苹果');

end;

procedure TForm1.RadioButton2Click(Sender: TObject);

begin

交易('葡萄');

end;

procedure TForm1.RadioButton3Click(Sender: TObject);

begin

交易('草莓');

end;

end.

这里是工厂方法模式的实现方法,在这种模式中

1、每一种水果都对应有一个小贩负责,这样他们做起生意来就轻松多了,呵呵!

2、顾客直接和小贩打交道,他知道您要什么,这样就不会因为说不清那讨厌的水果名字而吃不上说水果了。

//工厂类和水果类单元文件

unit FactoryMethod;

interface

type

接口_水果 = interface(IInterface)

function 提示():string;

function 被评价():string;

end;

类_苹果 = class(TInterfacedObject, 接口_水果)

function 提示():string;

function 被评价():string;

end;

类_葡萄 = class(TInterfacedObject, 接口_水果)

function 提示():string;

function 被评价():string;

end;

类_草莓 = class(TInterfacedObject, 接口_水果)

function 提示():string;

function 被评价():string;

end;

接口_小贩 = interface(IInterface)

function 工厂(): 接口_水果;

end;

类_苹果小贩 = class(TInterfacedObject, 接口_小贩)

function 工厂(): 接口_水果;

end;

类_葡萄小贩 = class(TInterfacedObject, 接口_小贩)

function 工厂(): 接口_水果;

end;

类_草莓小贩 = class(TInterfacedObject, 接口_小贩)

function 工厂(): 接口_水果;

end;

implementation

{****** 类_苹果 ******}

function 类_苹果.提示():string;

begin

result:='削了皮再吃!';

end;

function 类_苹果.被评价():string;

begin

result:='恩,还不错,挺甜!';

end;

{****** 类_葡萄 ******}

function 类_葡萄.提示():string;

begin

result:='别把核咽下去了!';

end;

function 类_葡萄.被评价():string;

begin

result:='没有核呀???';

end;

{****** 类_草莓 ******}

function 类_草莓.提示():string;

begin

result:='别怪我没告诉你,很酸!';

end;

function 类_草莓.被评价():string;

begin

result:='试试?哇,牙快酸掉了!';

end;

{***** 类_苹果小贩 *****}

function 类_苹果小贩.工厂(): 接口_水果;

begin

result:=类_苹果.Create()

end;

{***** 类_葡萄小贩 *****}

function 类_葡萄小贩.工厂(): 接口_水果;

begin

result:=类_葡萄.Create()

end;

{***** 类_草莓小贩 *****}

function 类_草莓小贩.工厂(): 接口_水果;

begin

result:=类_草莓.Create()

end;

end.

//窗体单元文件

unit MainForm;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls,FactoryMethod;

type

TForm1 = class(TForm)

RadioButton1: TRadioButton;

RadioButton2: TRadioButton;

RadioButton3: TRadioButton;

procedure RadioButton3Click(Sender: TObject);

procedure RadioButton2Click(Sender: TObject);

procedure RadioButton1Click(Sender: TObject);

private

procedure 交易(小贩:接口_小贩);

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.交易(小贩:接口_小贩);

var

我买的水果:接口_水果;

begin

我买的水果:=小贩.工厂();

ShowMessage(我买的水果.提示);

ShowMessage(我买的水果.被评价);

end;

procedure TForm1.RadioButton1Click(Sender: TObject);

begin

交易(类_苹果小贩.Create);

end;

procedure TForm1.RadioButton2Click(Sender: TObject);

begin

交易(类_葡萄小贩.Create);

end;

procedure TForm1.RadioButton3Click(Sender: TObject);

begin

交易(类_草莓小贩.Create);

end;

end.

夏天来了,西瓜上市了;

在简单工厂模式中,由于只有一个小贩,为了引进西瓜他只好对自己的工厂进行了修改;

在工厂方法模式中,由于每个小贩负责一种水果,只需要再引进一个卖西瓜的小贩就行了,对其他小贩的销售不会造成影响 。

下面先看看在简单工厂模式中是怎么做的:

1、在工厂类和水果类单元文件中,引入一个新的西瓜类(这里是扩展,不会影响到已有的代码)

//=============================================================================

类_西瓜 = class(TInterfacedObject, 接口_水果)

function 提示():string;

function 被评价():string;

end;

{****** 类_西瓜 ******}

function 类_西瓜.提示():string;

begin

result:='刚上市的沙瓤大西瓜,2元钱一斤!';

end;

function 类_西瓜.被评价():string;

begin

result:='靠,被骗了,根本没熟!';

end;

//=============================================================================

2、在工厂类和水果类单元文件中,修改小贩的工厂方法(这里是修改,已经违反了“开闭原则”)

//=============================================================================

class function 工厂类_小贩.工厂(水果名:string): 接口_水果;

begin

if(水果名='苹果')then result:=类_苹果.Create()

else if(水果名='葡萄')then result:=类_葡萄.Create()

else if(水果名='草莓')then result:=类_草莓.Create()

//请注意,下面这条语句是新加上去的,工厂被修改了!!!!

else if(水果名='西瓜')then result:=类_西瓜.Create();

end;

//=============================================================================

3、在窗体单元文件中,添加一个新的事件处理过程(这里是扩展,不会影响到已有的代码)

//=============================================================================

RadioButton4: TRadioButton;

procedure RadioButton4Click(Sender: TObject);

procedure TForm1.RadioButton4Click(Sender: TObject);

begin

交易('西瓜');

end;

//=============================================================================

下面再看看在工厂方法模式中是怎么做的:

1、这一步和在简单工厂模式中做的一样,在工厂类和水果类单元文件中,引入一个新的西瓜类(这里是扩展,不会影响到已有的代码)

//=============================================================================

类_西瓜 = class(TInterfacedObject, 接口_水果)

function 提示():string;

function 被评价():string;

end;

{****** 类_西瓜 ******}

function 类_西瓜.提示():string;

begin

result:='刚上市的沙瓤大西瓜,2元钱一斤!';

end;

function 类_西瓜.被评价():string;

begin

result:='靠,被骗了,根本没熟!';

end;

//=============================================================================

2、区别就在这里了,在工厂类和水果类单元文件中,引入一个新的西瓜小贩类(这里是扩展,不会影响到已有的代码)

//=============================================================================

类_西瓜小贩 = class(TInterfacedObject, 接口_小贩)

function 工厂(): 接口_水果;

end;

{***** 类_西瓜小贩 *****}

function 类_西瓜小贩.工厂(): 接口_水果;

begin

result:=类_西瓜.Create()

end;

//=============================================================================

3、在窗体单元文件中,添加一个新的事件处理过程(这里是扩展,不会影响到已有的代码)

//=============================================================================

RadioButton4: TRadioButton;

procedure RadioButton4Click(Sender: TObject);

procedure TForm1.RadioButton4Click(Sender: TObject);

begin

交易(类_西瓜小贩.Create);

end;

//=============================================================================

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有