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, 當然你可以進行擴充,比如後來我加入了OLE<->TOBJECT<->TDataset互換的功能。 主鍵生成機制,分頁存取功能,生成子集功能,及懶裝載功能,壓縮傳輸流功能等,同步數據更新問題等。這要你自己去發揮吧。 說了這麼多,話題轉回來吧。現在說客戶端怎麼去存取數據。 在前面中間層已經定義了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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章