0

我的问题与我在上一期(“将 Java 代码转换为 delphi 的问题”)中写的问题有关,但我仍然有问题。在我上一个问题中看到的 Java 代码是我试图转换为 Delphi 的工厂类的一部分。问题是我有一个名为的主接口IStandardDataProvider,其中包含工厂中不同类的常用方法。但是由于某些类还包含并非所有类都通用的其他方法。我使用从 interface 继承的另一个接口IStandardDataProvider。问题是我不能让泛型工作?在 java 中查看我的整个工厂类。这在 Delphi 中会是什么样子?

public class Factory {

    private static HashMap<String, IStandardDataProvider<?>> dataproviders = null;

    @SuppressWarnings("unchecked")
    public <T extends IStandardDataProvider<?>> T GetDataProvider(String dataProviderName) {
        if (dataproviders == null)
            buildDataProviderMap();
        if (dataproviders.containsKey(dataProviderName)) {
            return (T) dataproviders.get(dataProviderName);
        } else
            return null;
    }

    private void buildDataProviderMap() {
        // Build the database connection, that will be used in all the dataproviders
        DatabaseConnectionManager dbConnection = new DatabaseConnectionManager(ConfigurationManager.getConfiguration("sqlConnectionString"));

        // Instantiate the Hashmap 
        dataproviders = new HashMap<String, IStandardDataProvider<?>>();

        // Instantiate all the dataprovider implementations, and put them into the hash map
        dataproviders.put("EventDataProvider", new LocalEventDataProviderImpl(dbConnection));
        dataproviders.put("TaskActivityDataProvider", new LocalTaskActivityDataProviderImpl(dbConnection));
    }
}

更新:好的,这是我的 delphi 版本,我尝试使其通用。目前我只能访问IStandardDataProvider.

type
  TFactory = class(TObject)
  private
    DataProvider: TDictionary<string, IStandardDataProvider >;
    DbConnectionManager : TDatabaseConnectionManager;
    DBConnection : TSQLConnection;
    Configuration : TConfigurationManager;

    procedure BuildDataProviderMap;

  public
    constructor Create;
    destructor Destroy; override;

    function GetDataProvider(DataProviderName: string): IStandardDataProvider;
  end;

implementation

constructor TLocalDataProviderFactory.Create;
begin
  inherited Create;
  DbConnectionManager := TDatabaseConnectionManager.create;
end;

destructor TLocalDataProviderFactory.Destroy;
begin
  inherited;
  DbConnectionManager.Free;
  DataProvider.Free;
end;

function TLocalDataProviderFactory.GetDataProvider(DataProviderName: string): IStandardDataProvider;
begin
  if not Assigned(DataProvider) then
    BuildDataProviderMap;

  if DataProvider.ContainsKey(DataProviderName) then
  begin
    Result := DataProvider.Items[DataProviderName];
  end
  else
  begin
    Result:= nil;
  end;
end;

procedure TLocalDataProviderFactory.BuildDataProviderMap;
begin
  DataProvider := TDictionary<string, IStandardDataProvider>.Create;
  Configuration := TConfigurationManager.Create;
  DBConnection := DbConnectionManager.GetConnection(Configuration.GetConfiguration('sqlConnectionString'));
  DataProvider.Add('EventDataProvider',TLocalEventDataProviderImpl.create(DBConnection) );
  DataProvider.Add('TaskActivityDataProvider',TLocalTaskActivityDataProviderImpl.create(DBConnection) );
end;

end.
4

1 回答 1

4

正如您在其他问题中所说的那样,Delphi 不像 Java 那样支持通配符泛型。你能得到的最接近的是这样的:

type
  IStandardDataProvider<T> = interface(IInterface)
    ...
  end;

type
  TLocalDataProviderFactory = class
  private
    DataProvider: TDictionary<string, IInterface>;
    DbConnectionManager : TDatabaseConnectionManager;
    DBConnection : TSQLConnection;
    Configuration : TConfigurationManager;

    procedure BuildDataProviderMap;

  public
    constructor Create;
    destructor Destroy; override;

    function GetDataProvider<T>(DataProviderName: string): IStandardDataProvider<T>;
  end;

implementation

constructor TLocalDataProviderFactory.Create;
begin
  inherited Create;
  DbConnectionManager := TDatabaseConnectionManager.create;
end;

destructor TLocalDataProviderFactory.Destroy;
begin
  inherited;
  DbConnectionManager.Free;
  DataProvider.Free;
end;

function TLocalDataProviderFactory.GetDataProvider<T>(DataProviderName: string): IStandardDataProvider<T>;
begin
  if not Assigned(DataProvider) then
    BuildDataProviderMap;

  if DataProvider.ContainsKey(DataProviderName) then
    Result := DataProvider.Items[DataProviderName] as IStandardDataProvider<T>
  else
    Result := nil;
end;

procedure TLocalDataProviderFactory.BuildDataProviderMap;
begin
  DataProvider := TDictionary<string, IInterface>.Create;
  Configuration := TConfigurationManager.Create;
  DBConnection := DbConnectionManager.GetConnection(Configuration.GetConfiguration('sqlConnectionString'));
  DataProvider.Add('EventDataProvider', TLocalEventDataProviderImpl.Create(DBConnection) as IInterface);
  DataProvider.Add('TaskActivityDataProvider', TLocalTaskActivityDataProviderImpl.Create(DBConnection) as IInterface);
end;

end.

这真的对你没有帮助,因为你需要知道实现的具体类IStandardDataProvider<T>才能调用GetDataProvider(),例如:

var
  Provider: IStandardDataProvider<TUpdateTest>;

Provider := Factory.GetDataProvider<TUpdateTest>('EventDataProvider');

否则,忘记尝试让工厂本身支持泛型,而是让调用代码处理它,例如:

type
  IStandardDataProvider<T> = interface(IInterface)
    ...
  end;

  IEventDataProvider = interface(IStandardDataProvider <TUpdateTest>)
    ...
  end;

type
  TLocalDataProviderFactory = class
  private
    DataProvider: TDictionary<string, IInterface>;
    DbConnectionManager : TDatabaseConnectionManager;
    DBConnection : TSQLConnection;
    Configuration : TConfigurationManager;

    procedure BuildDataProviderMap;

  public
    constructor Create;
    destructor Destroy; override;

    function GetDataProvider(DataProviderName: string): IInterface;
  end;

implementation

constructor TLocalDataProviderFactory.Create;
begin
  inherited Create;
  DbConnectionManager := TDatabaseConnectionManager.create;
end;

destructor TLocalDataProviderFactory.Destroy;
begin
  inherited;
  DbConnectionManager.Free;
  DataProvider.Free;
end;

function TLocalDataProviderFactory.GetDataProvider(DataProviderName: string): IInterface;
begin
  if not Assigned(DataProvider) then
    BuildDataProviderMap;

  if DataProvider.ContainsKey(DataProviderName) then
    Result := DataProvider.Items[DataProviderName]
  else
    Result := nil;
end;

procedure TLocalDataProviderFactory.BuildDataProviderMap;
begin
  DataProvider := TDictionary<string, IInterface>.Create;
  Configuration := TConfigurationManager.Create;
  DBConnection := DbConnectionManager.GetConnection(Configuration.GetConfiguration('sqlConnectionString'));
  DataProvider.Add('EventDataProvider', TLocalEventDataProviderImpl.Create(DBConnection) as IInterface);
  DataProvider.Add('TaskActivityDataProvider', TLocalTaskActivityDataProviderImpl.Create(DBConnection) as IInterface);
end;

end.

var
  Provider: IEventDataProvider;

Provider := Factory.GetDataProvider('EventDataProvider') as IEventDataProvider;
于 2013-11-13T20:14:21.840 回答