分享
 
 
 

设计模式在制作升级文件包中的应用

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

设计模式在制作升级文件包中的应用

钱波 钱晓贤 高春玲

引言

软件系统的复杂性越来越大,而现有的类库也已经不能满足工程的需要,软件开发小组得到的建议是除了软件本身的特性突出,快速投放市场,成本低以外,还有性能和安全,并且软件能够做到改动容易,能及时交付,升级快速。软件构架的确会成为首要目标,但是架构可能很难说清楚是怎么回事,因为事实并不会如设计师所愿,设计展开以后,需求和构架解决方案将会越来越具体,设计师该怎样做呢?

设计模式的提出

模式在构造复杂系统得重要性已经在其它领域被认可,软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。灵活使用各种设计模式看来便成了一种设计上的技巧,已有的设计模式确实提供了设计的基础,但是设计模式并不是限于成规,关键在于怎样灵活的运用。

实例升级文件的制作

我们的文件是所需信息和几个文件的合并,后来在需要的基础上进行压缩,当然,升级文件下载后正好使个相反的过程,解压缩后分拆文件,然后把它们放置到合适的目录下去,实际上这个过程也可以看作是备份文件的产生和备份恢复。使用继承是添加功能的有效途径,我们可以在以前的类上派生一个类添加解压缩的功能,在完成以后就可以使用新增的功能了,这的确是一个方法,但是还有更为灵活的方法,更容易理解和分拆功能。我们可以利用模式装饰者,模式装饰者是一种对象结构型模式,就增加功能来说,使用继承是添加功能的一种有效途径,但是Decorator 模式比生成子类更为灵活。

现在首先分拆功能,可能是这样的:

图一 功能拆分类图

从图一上看,TFileInfo 类实际上是我们的接口,是位于顶层的类,现在主要需要的是三个继承者,1合并文件类TFileInfoReadIn,2分拆文件的类,TFileInfoReadOut,3解压缩类TZipFile,在开始的时候并没有构造TFileInfo这样一个顶层类,。因为看起来并不需要他,我们可以用单独的TFileInfoReadIn 对象来构建合并的程序,完成后交给TZipFile的去压缩,在反过来的过程中用TZipFile对象来解压文件,用TFileInfoReadOut来分解文件到目录中去。功能已经比较单一了。

如图一所示,现在试着用一个抽象的基类来同时操纵三个可能毫不相关的类,它们的接口函数并不一定统一,强行定义统一的接口可能不太好理解,但是在顶层类还是这样定义了:

procedure OpBaseList(var ls:TStrings);virtual;abstract; //操纵信息字段

procedure OpFileList;virtual;abstract; //操纵所有文件

OpBaseList函数是操纵文件前所加的其他信息字段,OpFileList将操纵所有的文件,因为是纯抽象的函数,即不用去实现它们,(另外需要说明的是,顶层类根据可能还需要扩充更多的接口函数)。在顶层类里维护了一个文件信息列表:FileList:TStringList,包含了所有文件的路径列表。(所有类只列出接口,详细请看源码)

Type TFileInfo=Class(TPersistent)

public

Procedure OpBaseList(var ls:TStrings);virtual;abstract; //操纵信息字段

Procedure OpFileList;virtual;abstract; //操纵所有文件

end;

关键的一步在于建立装饰类:

Type TFileDecorator=Class(TFileInfo)

public

Constructor Create(FileInfo:TFileInfo);

procedure OpBaseList(var ls:TStrings);override;

procedure OpFileList;override;

end;

也许装饰类看以来比较怪异,他维护了一个TFileInfo的私有对象,事实上它是连接其他从TFileInfo类继承的对象的连接者,m_FileInfo对象引用了构造函数传进的对象FileInfo.

Constructor TFileDecorator.Create(FileInfo: TFileInfo);

begin

m_FileInfo:=FileInfo;

end;

在OpBaseList和OpFileList接口中看起来更为简单:

procedure TFileDecorator.OpBaseList(var ls: TStrings);

begin

// inherited;

if m_FileInfo<>nil then

m_FileInfo.OpBaseList(ls);

end;

procedure TFileDecorator.OpFileList;

begin

// inherited;

if m_FileInfo<> nil then

m_FileInfo.OpFileList;

end;

看起来构造器中传进来的对象开始发生作用。好,接下来的工作是实现三个功能类,实际的代码将放在功能类中:

type TFileInfoReadIn=class(TFileDecorator)

protected

procedure WriteAFileIn(FilePathName:String); //写入一个文件

public

constructor Create(FileInfo:TFileInfo;FileName:String); //

procedure OpBaseList(var ls:TStrings);override; //操纵信息列表

procedure OpFileList;override; //操纵所有文件

end;

type TFileInfoReadOut=class(TFileDecorator)

public

constructor Create(FileInfo:TFileInfo;FileName:String);

procedure OpBaseList(var ls:TStrings);override;

procedure OpFileList;override;

end;

现在看实现类TFileInfoReadIn.OpFileList函数,怎样操纵文件:

procedure TFileInfoReadIn.OpFileList;

var I:Integer;

begin

inherited; //继承功能

m_Writer.WriteInteger(m_FileList.Count);//写入文件的个数

for I:=0 to m_FileList.Count-1 do begin

WriteAFileIn(m_FileList.Strings[I]); //根据文件全路径写入文件

end;

if Assigned(m_Writer) then

FreeAndNil(m_Writer);

if Assigned(m_FileStream) then

FreeAndNil(m_FileStream);

end;

WriteAFileIn函数实现:

procedure TFileInfoReadIn.WriteAFileIn(FilePathName: String);

var ReadInt:Integer;

FSource:TFileStream;

begin

FSource:=TFileStream.Create(FilePathName,fmOpenRead); //这里重新创建文件输入流

m_Writer.WriteInteger(FSource.Size); //写入文件的长度

m_Writer.WriteString(ExtractFileName(FilePathName)); //写入文件名

repeat

ReadInt:=FSource.Read(m_buffer^,BUFFER_SIZE); //源文件内容读入缓冲

m_Writer.Write(m_Buffer^,ReadInt);

until ReadInt<BUFFER_SIZE;//文件的内容 //重复读取写入文件过程

FreeAndNil(FSource); //释放文件流

end;

至于TFileInfoReadOut类的OpFileList实现函数,和TFileInfoReadIn过程相反,这里就不列出了,具体看源代码。

关键还在于第三个类TZipFile,这个类,实现了文件的压缩和解压,首先单元里加上ZLib单元,这样我们可以利用TCompressStream类来实现文件流的压缩和解压,这里有一个问题,TZipFile类利是其他的程序员交付过来的,接口并不统一,但是适配器模式可以让我们很好地解决这类问题。

图二 为装饰类加入适配器

图二所示,TZipFile包含了CompressFile()和DeCompressFile()函数,而接口OpBaseList和OpFileList不变,实际上TZipFile可以被称为适配器。

type TZipFile=class(TFileDecorator)

private

m_ZipFileName:String;

public

Constructor Create(FileInfo:TFileInfo;FileName:String='');

Destructor Destroy;override;

function CompressFile(const SrcFile, DesFile: string;……. ): TCompressResult;

//压缩文件

function DeCompressFile(const SrcFile, DesFile: string;………):TCompressResult;

//解压文件

procedure OpBaseList(var ls:TStrings);override; //接口依然是这两个,但这个接口什么////都不做

procedure OpFileList;override; // 调用压缩和解压

end;

解释完模式后看看我们怎么运用我们的模式,如图三是制作的这个小工具的界面:

图三 工具界面

图三是我们的界面,添加完文件后触发打包按钮,Exe文件目录下会出现以文件名称Edit框(Edt_Edition)为文件名的合并文件Edt_Edition.dat文件和压缩文件Edt_Edttion.pag。在windows2000和Delphi7下调试成功,解包过程相反。

点击添加文件后,文件显示列表里会加上所需要的文件,现在的门面功能即是将TEdit盒子里的信息内容写入目标文件A,然后将列表中的文件合并到文件A里面,最后进行压缩。

现在可以定义一个aRead 和aZip 对象

var aREAD:TFileInfoReadIn; aZip:TZipFile;

begin

aRead:=TFileInfoReadIn.Create(nil,’FileName’);

////////………

aZip:=TZipFile.Create(aRead); //aZip对象添加aRead对象

OperatorFile(aZip); //操纵aZip对象

aRead.Free;

aZip.Free;

end;

操作文件很简单,调用两个接口函数

procedure TMainFrm.OperatorFile(Obj: TFileInfo);

begin

obj.OpBaseList(F_Strings);

obj.OpFileList; //如果还有其他接口,可以在这里逐个调用

end;

如果根据需要不用压缩文件,很简单,aZip:=TZipFile.Create(aRead)这句去掉即可。又如果我们写出了新的算法去压缩,可以修改TZipFile,也可能的调用方式就是一句aNewZip:=TNewZipFile.Create(aRead);你还可以以这种方式:

TFileInfoObj:=TFileInfoA.Create(TFileInfoB.Create(TFileInfoC.Create(…)));

然后调用接口TFileInfoObj.OpFileList; 一句话将所有对象的接口一次全都调用。最重要的是功能可以拆分:例如

TFileInfoObj:=TFileInfoB.Create(TFileInfoC.Create));

TFileInfoObj:=TFileInfoA.Create(nil);

TFileInfoObj:=TFileInfoB.Create(TFileInfoA.Create(nil));

////////

这样功能变成可设计的,就像是搭积木,在接口不合适的地方不要忘了适配器等结构型模式。

小结

事实上,考查一下Delphi的TStream和TMemoryStream,TFileStream,TCompressStream 等本身就是一个极好的装饰样式的实例。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有