java delphi 三层_DELPHI三层架构设计方案

随便说说最近项目中的三层架构吧。讲点实际的东西。我最讨厌空讲道理。网上讲道理的太多了,不喜欢举例子。

大多数文章中都或多或少的讲到了三层架构。表示层,业务层,数据层。又把业务层再细分,分为外观服务层,主业务服务,及数据库库服务层。

今天主要讨论一下业务层吧。举个最简单的例子。客户端获取数据。

业务层要与表示层尽量解藕, 我的方法是:首先我们在中间层TLB_中定义一个接口 IBusinessService,

定义一个方法。getvoList,我要得到一个VO的列表, VO即ValueObject, 例如:

TValueObject= class(TPersistent)

private

b_insertFlag :Boolean;

b_updateFlag :Boolean;

b_deleteFlag :Boolean;

d_rowVersion :double;

procedure setInsertFlag(pInsertFlag

:Boolean);

function getInsertFlag:

Boolean;

procedure setUpdateFlag(pUpdateFlag

:Boolean);

function getUpdateFlag:

Boolean;

procedure setDeleteFlag(pDeleteFlag

:Boolean);

function getDeleteFlag:

Boolean;

procedure setRowVersion(pRowVersion

:double);

function getRowVersion:double;

protected

function  GetOLEData:

OleVariant; virtual;

procedure SetOLEData(const

Value: OleVariant); virtual;

published

property bInsertFlag:

Boolean read getInsertFlag write setInsertFlag;

property bUpdateFlag:

Boolean read getUpdateFlag write setUpdateFlag;

property bDeleteFlag:

Boolean read getDeleteFlag write setDeleteFlag;

property dRowVersion:

double read getRowVersion write setRowVersion;

property POLEData:OleVariant

read GetOLEData write SetOLEData;

end;

TUserVO = class(TValueObject)

private

id: string;

name: string;

password: string;

。。。。。。。。。。。。。。。

VO的列表:

TValueObjectList = Class(TObjectList)

private

ValueObject: TValueObject;

ClassName: TClass;

procedure setClassName(pTmpClsName

:TClass);

function getClassName:

TClass;

procedure setValueObject(pTmpVO

:TValueObject);

function getValueObject:

TValueObject;

protected

function GetOLEData:

OleVariant; virtual;

procedure SetOLEData(const

Value: OleVariant); virtual;

published

function AddItem(index:

integer; AObject: TObject ):Integer; virtual;

function GetItem(index,

itemid: integer ): TObject; virtual;

function CountItem:Integer;

virtual;

public

constructor Create; virtual;

destructor Destroy; override;

procedure AfterConstruction;

override;

property PClassName:

TClass read getClassName write setClassName;

property POLEData: OleVariant

read GetOLEData write SetOLEData;

property PValueObject:

TValueObject read getValueObject write setValueObject;

end;

TValueObjectList就是VO的装载器。在 JAVA中有一个好听的叫法,

VOList值列表组装器,具体的功能是可以管理VO, 当然你可以进行扩充,比如后来我加入了OLETOBJECTTDataset互换的功能。

主键生成机制,分页存取功能,生成子集功能,及懒装载功能,压缩传输流功能等,同步数据更新问题等。这要你自己去发挥吧。

说了这么多,话题转回来吧。现在说客户端怎么去存取数据。

在前面中间层已经定义了IBusinessService, 定义一个方法。getvoList,这个就是通用存取数据的接口了。

下面看看他的完整形式:

procedure getvoList(const sBOName:

WideString; const sBOService: WideString;

out voListObj: OleVariant);

这里有三个参数,sBOName:sBOService:voListObj:

干什么用的?第一个就是业务对象名称, 第二个是业务对象服务名称,第三个是传回来的olevariant;

强调一点。sBOName:sBOService:这两个参数并不直接对应中间层的业务对象。之间加了一个转换层。也就是service定位层。这个东西把客户传来的两个参数定位到相应的业务对象中。有什么好处呢。其实就相当于客户端和中间层的一个简单的协议,客户端发一个boname,一个服务名,这都是约定的。也就是不变的。以后该业务要变,就十分方便,只需要在中间层的定位器,配置一下就可以了,如果采用XML或文件配置,不需要修改任何程序,客户的业务已经发生改变

当然会采用名字调用等技术了。相关代码如下:

TBOService= class(TServiceObject)

private

//srvOBName : String;

IBasBO: IBaseBO;

BOPool: TBOPrototype;

//业务对象持久池:

public

constructor Create;

procedure getvoList(const

sBOName: WideString; const sBOService: WideString;

out voListObj: OleVariant); safecall;

。。。。。。。。。。。。。。。。。。。。。

再说说TBOPrototype吧 ,这个东西是管理业务对象池的。由他统一创建业务对象。采用的是单例模式。

之后具体的调用,相关代码如下:

if FindClass(fClsPer.ClassName) <> nil then

begin

tmpPer := TPersistentClass(FindClass(fClsPer.ClassName)).Create;

Supports(tmpPer, StringToGUID('{3AE5EA91-41EA-41E7-B40C-CF00F8B75F8A}'),

IBasBO);

try

IBasBO.InitBusinessObj;

voListObj

:= IBasBO.GetDAOValueObject.getDAOValueList;

finally

IBasBO :=

nil;

end;

end

else

ShowMessage('no found!');

其中IBasBO,是一个接口定义,

IBaseBO = interface(IUnknown)

['{3AE5EA91-41EA-41E7-B40C-CF00F8B75F8A}']

function GetObject: TObject;

procedure SetObject( value: TObject

);

function GetDAOValueObject: TDAOValueObject;

procedure SetDAOValueObject(tmpDAOVO:

TDAOValueObject);

procedure InitBusinessObj;

end;

呵呵,现在可以看到冰山一角了吧。

经过业务对象初始化之后,他就去创建DAO了。。。呵呵。 如果你不了解DAO,看看相关的资料吧。。。。。

主要功能就是把数据存储隐藏起来,调用SQL, ORACLE,之类。我主要是用它调用数据库工厂创建。

大致看一下代码吧。

//--------------------------------------------------------------------------

//1.工厂基类(SQLServer工厂类)

//--------------------------------------------------------------------------

unit ConnDBFactory_SQLServer;

interface

uses

Classes, ADODB, ConnDB, DB, DBTables, Controls,

Dialogs, IConnDB, ConnDBFactory;

type

TConnBDEDBFactory_SQLServer = class(TConnDBFactory)

public

function CreatorConnDB()

:IConnDataBase; override;

end;

TConnADODBFactory_SQLServer = class(TConnDBFactory)

public

function CreatorConnDB()

:IConnDataBase; override;

end;

又扯远了,还是再回来吧。中间层的定位器通用业务对象管理器创建或获得一个业务对象之后,定位到相应的服务上去。比如数据存取。这里有一点说明:就是业务对象的数据存取和业务服务是分开的。

数据存取就采用DAO的方法。

直接一点说就是创建DAO对象。

这是  TDAOValueObject= class(TPersistent,

IDAOValueObject)

private..

.............

上面的是基类。完成基础服务的。看看接口吧。

IDAOValueObject = interface(IUnknown)

['{DF03C9E7-2A5B-4E32-8EF5-C4E8FC77E8BB}']

function createDAOValue: TValueObject;

function insertDAOValue(pValueObject:

TValueObject): Integer;

function updateDAOValue(pValueObject:

TValueObject) :Integer;

function deleteDAOValue(pValueObject:

TValueObject) :Integer;

function findByPrimaryKey(const pServiceName:

WideString;  vKey: OleVariant): TValueObject;

function getDAOValueList: OleVariant;  overload;

function getDAOValueList(sSQL:

String): OleVariant;  overload;

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

看看干了什么。。。。

inherited Create;

sqlAnySrvObj := TSQLAnalyzeService.Create;

if not assigned(VOList) then

VOList := TValueObjectList;

VOList.pVOClassName := ‘TUSERVO’

创建了一个SQL分析器。 一个VOLIST对象, 并且传了一个VO名字。。

TSQLAnalyzeService,SQL分析器可以动态的生成SQL脚本。。

再看看

function getDAOValueList: OleVariant;

overload;

function getDAOValueList(sSQL:

String): OleVariant;

这两个函式吧。 把生成的VO, olevariant化。

这些基础的工作, 已经由VOLIST做了。

重要的一点:

prepareTable,这是VOLIST中的函式,由他动态的生成TDATASET, 当然没必要在中间层生成。但可以打包传给客户端,就OK了。

现在在看一下客户端的代码吧:

MyInterface2.getvoList('TUserBO',

'' , oo);

pp := TValueObjectList.Create;

pp.OLEToDS(oo);

dataSource1.DataSet := pp.pDataSet;

呵呵,PP是公共的TVOLIST,发布到客户端。 通由Ole,自动生成了TDATASET。

想用对象,没问题,看下面:

定义:   ss: TVALUEOBJECT;

ss := TUserVO(pp.GetItem(1));

if ss<>nil then

ShowMessage((ss as TUserVO).pName);

之后,你想怎么样就怎么样了。。。。。

呵呵,下次再讲讲业务逻辑方面吧,希望给做DELPHI三层的兄弟一个参考。源码下载地:http://www.delphifans.com/SoftView/SoftView_2000.html

你可能感兴趣的:(java,delphi,三层)