关于创建类结构的想法

时间:2012-11-21 13:09:46

标签: delphi frameworks

我有一个用几个类和组件开发的框架。我想创建一个可以访问整个框架的主对象,以便所有开发人员都可以从一个位置访问这些方法。

示例:

MyApp.Framework.DataBase
MyApp.Framework.DateUtils
MyApp.Framework.Users
MyApp.Framework.System

对象MyApp映射整个框架,所有开发人员都可以随时访问。

主要问题是创建一个健壮且易于扩展的结构。过了一段时间,我将包括我们公司产品的功能和方法结构。

示例:

MyApp.Blog.    (functions about Blog product)
MyApp.WebDocs. (functions WebDocs product)

关于课程的更多示例:

TMyAppBase = Class
Private
  Function GetDatabase: TDataBaseClass;
  Function GetUsers: TSystemUsersClass;
  Function GetForms: TFormManager;
Public
  Constructor Create; Virtual;
  Destructor Destroy; Override;
  Property Database: TDataBaseClass Read GetDatabase;
  Property Users: TSystemUsersClass Read GetUsuarios;
  Property Forms: TFormManager Read GetForms;
End;

使用此课程:

var
  LMyApp: TMyAppBase 

begin
  ShowMessage(LMyApp.Users.ActiveUserName);
end;

那会是朋友吗,我希望你的想法可能。我的意图是创建一个单一而广泛的结构。

2 个答案:

答案 0 :(得分:2)

您不必为此创建一个类。

只需创建一个名为MyApp.Framework.DataBase的单位,依此类推。 Delphi以单位形式支持点,这样就可以创建“命名空间”。

当你开始在使用列表中输入Myapp.时,Delphi甚至会自动完成。

此外,您可以使用静态方法创建一个类TDataBase,您可以使用TDataBase.Method调用这些方法来组织通用范围内的简单函数/过程。

答案 1 :(得分:2)

正如我在评论中已经写过的那样,我认为在这种情况下,最好使用一个主要的服务(主要类,单身),它可以为您提供对其他服务的访问权限。您的所有模块都具有唯一ID(TGUID)。在程序执行开始时,他们应该在主服务中注册自己 例如。主要服务单位:

unit AppServices;

interface
uses generics.collections, rtti;
type
    // Unique ID Attribute for services
    ServiceIDAttribute = class(TCustomAttribute)
      strict private
        FId : TGUID;
      public
        constructor Create(ServiceID: string);
        property ID : TGUID read FId;
    end;

    //Services Base class
    TCustomAppService = class(TObject)
      strict protected
      public
    end;

    // Main Service Object
    TAppServices = class(TObject)
      strict private
       class var
        FServices : TObjectDictionary<TGUID, TCustomAppService>;
       var
      public
        class constructor Create();
        class destructor Destroy();
        class procedure RegisterService(aService : TCustomAppService);
        class function QueryService(ServiceID : TGUID):TCustomAppService;
    end;

class constructor&amp; destructor只是创建并释放FServices词典。 QueryService方法通过其唯一ID返回Service:

class function TAppServices.QueryService(ServiceID: TGUID): TCustomAppService;
begin
    result := nil;
    if FServices.ContainsKey(ServiceID) then
        result := FServices[ServiceID];
end;

方法RegisterService从参数的类名中提取RTTI属性(ServciceIDAttribute)并将此对(id-service)添加到字典中:

class procedure TAppServices.RegisterService(aService: TCustomAppService);
var ctx : TRttiContext;
    st : TRttiType;
    a : TCustomAttribute;
    id : TGUID;
begin
    ctx := TRttiContext.Create();
    try
        st := ctx.GetType(aService.ClassType);
        for a in st.GetAttributes() do begin
            if not (a is ServiceIDAttribute) then
                continue;
            id := ServiceIDAttribute(a).ID;

            FServices.AddOrSetValue(id, aService);
            break;
        end;
    finally
        ctx.Free();
    end;
end;

现在,关于终端服务。例如UserManager单元:

unit UserManager;

interface
uses AppServices;

const
    SID_UserManager : TGUID = '{D94C9E3A-E645-4749-AB15-02631F21EC4E}';
type
    [ServiceID('{D94C9E3A-E645-4749-AB15-02631F21EC4E}')]
    TUserManager = class(TCustomAppService)
      strict private
        FActiveUserName: string;
      public
        property ActiveUserName: string read FActiveUserName;
    end;


implementation


initialization
    TAppServices.RegisterService(TUserManager.Create());
end.

现在我们可以测试我们的代码:

procedure TestApp();
var uMgr :TUserManager;
    dbMgr : TDBmanager;
begin
    dbMgr := TAppServices.QueryService(SID_DBManager) as TDBManager;
    if dbMgr.Connected then
         writeln('connected!')
    else writeln('not connected');

    uMgr := TAppServices.QueryService(SID_UserManager) as TUserManager;
    writeln('Active user: ', uMgr.ActiveUserName);
end;

<强>摘要
TAppServices是主要对象,可以访问App中的任何服务。它对终端服务一无所知,因此它没有依赖性。您可以根据需要更改其实施。 您可以根据需要拥有尽可能多的TCustomAppService类后代。向应用程序添加新服务时,不应更改TAppServices类接口或实现。