delphi入门及实例详解(读Delphi面向对象编程思想二-模块化开发实现初探)
delphi入门及实例详解(读Delphi面向对象编程思想二-模块化开发实现初探)ProjectGroup |--- MainProject.dproj |---public |---UnitPublic.pas |---frmMain.pas |--- ProjectDll.dproj 这个案例中没有所谓的持久层,仅仅是一个案例,没有牵扯到文件读写或者数据库数据处理项目整体的目录结构一个设计良好的应用程序在逻辑上应该至少划分为界面和业务两个层次。界面和业务的分离将十分有利于系统的维护和扩展,体现灵活、复用的风格。一个面向对象的程序比传统的面向函数和过程的程序更易于实现界面和业务的分离通常的软件系统划分为3层,即:表现层(或者称为表示层)、业务层和数据层,如下图所示该案例就一个目的,实现DLL中导出一个对象,尝试实现功能模块分离,我自己有一个习惯就是,在学习任何新东西之初都会先跑一个Hello
接上一篇:读Delphi面向对象编程思想一
界面和业务的分离是开发可维护、易扩展、长寿命应用系统的关键,也是实现多层分布式系统的必经之路。面向对象编程技术为开发界面和业务分离的系统提供了行之有效的途径
以上内容摘自原书
在逻辑上,代码的封装是通过类来实现的,类通过属性封装了对象的数据,类通过方法封装了对象的行为。在屋里上,代码可以封装在可执行文件中(.exe)、动态链接库中(.DLL)、也可以封装在COM 组件中,而对代码或程序的封装,我们在上一篇文章中也提到过主要是在于实现易开发、可维护、能服用的软件模式
一个设计良好的应用程序在逻辑上应该至少划分为界面和业务两个层次。界面和业务的分离将十分有利于系统的维护和扩展,体现灵活、复用的风格。一个面向对象的程序比传统的面向函数和过程的程序更易于实现界面和业务的分离
通常的软件系统划分为3层,即:表现层(或者称为表示层)、业务层和数据层,如下图所示
- 表现层:主要用于和用户交互,它提供用户界面及操作导航服务,它的主要选项是win32客户机和基于浏览器的客户机
- 业务层:主要用于业务处理,提供商业逻辑等各种约束
- 数据层:主要用于数据的集成存储,这些数据既可以是文件,也可以是数据
该案例就一个目的,实现DLL中导出一个对象,尝试实现功能模块分离,我自己有一个习惯就是,在学习任何新东西之初都会先跑一个HelloWorld的 案例,在不掺杂其他复杂的业务功能之前能够跑通的话至少说明思路、环境没有问题,剩下的就是在这个基础上进行扩展了,根据上面分析的思路,我们来写一个
项目整体的目录结构
ProjectGroup
|--- MainProject.dproj
|---public
|---UnitPublic.pas
|---frmMain.pas
|--- ProjectDll.dproj
这个案例中没有所谓的持久层,仅仅是一个案例,没有牵扯到文件读写或者数据库数据处理
具体的代码实现
- 可执行文件所在的项目代码(MainProject)
public文件夹下的UnitPublic单元中的代码如下
//需要注意的是这个单元最好存放的全部都是接口,而不存放其他的内容,接口的主要目的可以当做exe和dll两个项目实现单元共享的桥梁
type
IUtile = interface
['{BF70EF99-0F0C-4726-B29B-56E665C8496A}']
function ShowMessage(): string;
end;
implementation
end.
exe项目文件的代码如下
//... 只存放实现部分的代码,interface部分的代码不变,全复制太多了
implementation
uses
UnitPublic;
{$R *.dfm}
//我们引入DLL中的一个导出函数,而该函数返回的数据类型是一个接口类型
function GetPublicUtil(): IUtile; stdcall; external 'ProjectDll.dll';
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(GetPublicUtil().ShowMessage());
end;
end.
dll项目中的代码如下
library ProjectDll;
//这里唯一的难题就是我们需要引用UnitPublic单元,而该单元是在另外一个项目的,解决办法指定对应的路径即可
uses
UnitPublic in '../MainProject/public/UnitPublic.pas'
System.SysUtils
System.Classes;
{$R *.res}
type
//实现对应的接口,重写对应的抽象方法
TPublicUtil = class(TInterfacedObject IUtile)
public
//注意该方法是接口中定义的抽象方法,如果该方法一旦被调用成功,那么也就意味着我们整个流程跑通
function ShowMessage(): string;
end;
{ TPublicUtil }
function TPublicUtil.ShowMessage: string;
begin
Result := 'HelloWorld';
end;
//这个函数才是整个的核心,其返回值返回的是接口实现类的对象,根据多态的特性,父类类型是可以接收子类对象的
function GetPublicUtil(): IUtile; stdcall;
begin
Result := TPublicUtil.Create;
end;
//导出函数列表
exports
GetPublicUtil;
逻辑分离
如果一个项目的代码较少(这里是相对于大型项目来说的),那么我们可以考虑不再实现物理分离,仅仅做一个逻辑分离,按照各自功能的不同划分对应的单元即可,下面这张图是用于说明
在大型项目中,我们除了逻辑分离之外那么久必须还要进行物理分离,所谓的物理分离就是我们不光对使用频率较高的功能进行模块封装之外还要将其以dll或者其他的文件表达方式进行封装,好处当然还是 代码复用,现在大家考虑更多的可能是自己完成某一个软件,但是现在很多时候已经不是单兵作战了
总结:上面我们进行了各种思路的分离,除了我们在做日常开发时需要的某些扩展维护之外,书上还简单的阐述了利用webservice实现分布式软件架构的开发,这个不在我们现在的讨论范围之内,因为它是一个很大的话题,单单分布式就可以写本书了