我正在使用Delphi XE设计我的第一个3层应用程序。我想以这样一种方式定义我的业务对象和数据访问对象,使业务对象不必知道实际使用的数据访问对象的版本。
我的业务对象层中有一个功能,如下所示:
function TCustomer.Load(sSearch: string; iType: Integer; var sError: string) : Boolean;
var myDAL : Tdalbase; // a base Data Access Layer class
myData : TDataSet;
begin
Result := False;
try
myDal := GetDalObject(OBTYPE_CUSTOMER); // factory method that returns the appropriate DAL class for the business object type depending on the database in use.
myData := myDal.LoadFromDatabase(sSearch, iType, sError); // abstract error occurs here
<blah loads the properties of TCustomer from the returned dataset>
End;
在其他地方我已经声明了TdalBase,TdalSQLbase(TDalBase的子类)和TdalSQLCustomer(TdalSQLBase的子类)
TdalBase和TdalSQLbase有一个虚拟抽象函数“LoadFromDatabase”。 TdalSQLCustomer使用override指令实现该方法; GetDalObject(OBTYPE_CUSTOMER)返回一个TdalSQLCustomer。
但是当调用myDal.LoadFromDatabase时出现抽象错误。大概是因为我已经将方法中的var声明为TDalBase,它试图从该父类运行该函数,而不是TdalSQLCustomer版本。
我不希望我的TCustomer对象知道它实际上是什么版本的TdalBase,因为它可能是TdalSQLCustomer,或者其他一些实现(例如TdalMySQLCustomer)。
是否可以避免抽象错误,仍然可以隐藏TCustomer中的实例化类?
我将补充一点,如果在Delphi XE中有ORM工具可以帮助解决这个问题,我很乐意尝试任何建议。不过,我也想了解这些东西的基本原理。
非常感谢, 理查德
感谢您的评论。就我所知,GetDALObject做了正确的事情:
uses
dalSQLCustomer;
function GetDalObject(iType : Integer) : TdalBase;
begin
case dbType of
DBTYPE_SQL : Result := GetSQLDalObject(iType);
end;
end;
function GetSQLDalObject(iType : Integer) : TdalSQLBase;
begin
case iType of
OBTYPE_CUSTOMER : Result := TSQLCustomer.Create;
end;
end;
TSQLCustomer界面如下:
type TSQLCustomer = class(TdalSQLBase)
public
function LoadFromDatabase(sSearch :String; iType : Integer; var sError : String) : TDataSet; override;
function SaveToDatabase(sError : String) : Boolean; override;
function DeleteFromDatabase(sError : String) : Boolean; override;
private
function LoadCommand(sSearch :String; iType : Integer; var sError : String): String;
end;