Delphi程序设计之--惯用法(2)

2008-04-10 02:57:10来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折


//项目:要求你对一个数据集支持多种输出显示方式

...例子,以后给出

//* 说明:
1、“多种输出方式”,说明输出方式在今后的应用中可能会经常扩充,因此要在程序设计时考虑到输出方式的易扩充性。
2、参考VCL中,控件注册(RegisterComponents)的机制,可以发现VCL中大量的使用到了注册机制;其中比较经典的就是控件属性编辑器的注册了。
*//

{ No. 7 }使用预定义控制程序版本

//如果您做的是一个二次开发平台的程序,则必须涉及到产品版本控制和项目版本控制问题
//通常使用预定义的方式控制

//语句比较简单了就是:
{$DEFINE JOYYUAN97}
{$IFDEF JOYYUAN97} {ELSE} {ENDIF}
{$UNDEF JOYYUAN97}

*说明:
1、将预定义划分在多个单独的文件中。
2、在每个单元的最前头但在Unit 后,使用{$I ...} 将文件包含(Include)进当前单元
3、根据预定义情况控制当前单元所能包含的单元文件
4、尽量单独划分一个针对项目的预定义文件在包含所有预定义文件后,包含此文件,则在此文件中,可以针对项目的需要,将取消部分预定义{$UNDEF JOYYUAN97}
*//

{ No. 8 } 使用函数指针,减少单元项目包含

//我经常的认为减少单元的包含,是做公共单元的第一步,所以在如何尽量减少单元包含
//也就是如何减少程序单元的耦合性上,应多下工夫。

{ 情景描述:
TMyFormManager: 窗体管理类
TMyForm:数据窗体基础类
TMyFormAccess:窗体信息保存和读取类。将窗体信息保存到数据库或其他什么类型的结构中
分析:
1、窗体基础类(TMyForm) 和 窗体管理类(TMyFormManager)需要在一个单元 uManagers中实现。
2、窗体具体实现类(TMyImageForm)单元 fMyImange 需要包含单元uManagers,进行窗体继承,和窗体管理。
3、窗体数据读取类(TMyFormAccess)单元 uMyAccess 需要包含单元uManagers和单元fMyImange
问题:
如果我希望实现窗体保存,那么应该在窗体的某个按钮事件中实现。则涉及到窗体单元需要包含窗体数据访问类单元,而如果放在窗体基础类中,则单元uManager又必须包含单元uMyAccess。
当数据访问,即数据存储格式会根据要求而改变并要求可扩充时,则单元包含必定是一个隐患。
解决办法:使用函数指针变量。
1、在单元uManagers中定义一个,保存数据信息的函数指针变量。
2、在应用程序初始化的时候给这个函数指针变量赋值。
3、在需要保存窗体信息时,判断如果指针不为空,则执行函数保存窗体信息。

{ No. 9 } 常量,认识常量,使用常量
有很多书都都介绍了常量定义的重要性,我也会经常想到,但是看看VCL源码才知道,自己忽略了,别人对常量的使用情况。

1、我们经常使用的消息的定义就是:声明一个常量,然后在适当的时候使用之。
通常定义和使用:
const
WD_MyMessage = WM_User 101;
type
TMyForm = class(TForm)
...
procedure WDMyMessage(var message: TMessage); message WD_MyMessage; {响应消息位置}
end;
但是,如果您将{响应消息位置}语句改写为:
procedure WDMyMessage(var message: TMessage); message WM_User 101;
同样,编译可以成功,使用也正常。所以,常量定义在Window系统处理和接口中应用非常普遍。

2、在Delphi中,我们定义了颜色变量,clRed, clGreen等,也都是定义的常量,便于以后的使用。通过这个观察我发现,常量的定义应该是在项目中,可部分复用的,所以,可以定义一个标准常量单元,以便在个项目中,复用定义的常量。

{ No. 10 }一个Delphi中,常用到的数组

对TIdentMapEntryd类型的数组定义和使用,Delphi中,有比较完善的实现。
TIdentMapEntry = record
Value: Integer;
Name: String;
end;

1、数组定义:array[0..ArrMax] of TIdentMapEntry
可参考:Controls单元中:
Cursors: array[0..21] of TIdentMapEntry = (
...
);
2、两个互相求值得函数: IntToIdent(由Value求Name)和 IdentToInt(由Name求Value);
具体应用可以参考:IdentToCursor 和 CursorToIdent。

3、应用:a、直接应用此树组定义方式和数组操纵函数;b、学习函数中,对数组访问和操纵的方式。c、学习标准的信息访问函数定义: function IntToIdent(Int: Longint; var Ident: string; const Map: array of TIdentMapEntry): Boolean; 具体返回的信息由参数方式返回回来,至于访问是否有效,则通过函数的布尔返回值加以判断。

{ No. 11 } 由特例到普通的发现
我通过对 Cursors 的定义和操作函数的跟踪发现:
1、如 { No. 10 }中介绍的,将Cursors的定义和一般操作通用化。
2、提供 Int 和 Ident互转化的函数。
3、提供数组列表信息循读取的函数: GetCursorValues;其中,使用了 { No. 3 } 中介绍的“事件指针 做参数”读取列表信息的方法。

{ No. 6 } 的补充:
例子:
procedure RegisterComponents(const Page: string;
ComponentClasses: array of TComponentClass);
begin
if Assigned(RegisterComponentsProc) then
RegisterComponentsProc(Page, ComponentClasses)
else
raise EComponentError.CreateRes(@SRegisterError);
end;

解读:
1、使用注册的方式,记录可使用的控件的类型等。
3、对于 RegisterComponentsProc 使用了{ No. 8 } 中“使用函数指针,减少单元项目包含”的方法,便于将来程序的扩充,版本的升级等。

{ No. 11 }只定义一个公共函数
//项目描述:现在要实现一个CAD画图或Visio系统,要求有好的扩展性和易维护性;
//并且要求耦合性低,便于,将来系统的部分或扩展后的系统封装后,直接在今后的项目中使用

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:华为CMPP源码delphi6版

下一篇:程序设计和调试中的几点总结