Du brauchst hier eine
Fabrikmethode oder eine
Factory.
Delphi-Quellcode:
// Fabrikmethode
// darf auch virtuell sein, damit man die implementierende Klasse von IUser
// ändern kann
function TUserFinder.CreateUser(UserID:Integer):IUser;
begin
Result := TUser.Create(UserID);
end;
function TUserFinder.Find(
const Username:
string): IList<IUser>;
var
Query : IDbQuery;
begin
Query := FDatabase.GetQuery();
Query.SQL := '
SELECT * FROM Users WHERE username = :username';
Query.Parameters.Add('
:username', Username);
Query.Open();
try
Result := TList<IUser>.Create();
for each Dataset
in Query.Results
do
begin
// User erzeugen mit Fabrikmethode
User := CreateUser(
Query['
IdUser']);
User.Username := Username;
User.LastLogon :=
Query['
LastLogon'];
...
Result.Add(User);
end;
finally
Query.Close();
end;
end;
Mit einer Factory sieht das so aus:
Delphi-Quellcode:
TUserFactory =
class(TObject)
public
class function CreateUser(UserID:integer):IUser;
virtual;
end
//===============
// Jenachdem ob nur in der Find-Methode neue IUser-Objekte erzeugt werden müssen,
// oder ob noch andere Methoden die Factory benötigen
// übergibt man die Factory als Parameter oder als Property der Klasse TUserFinder
function TUserFinder.Find(
const Username:
string; UF:TUserFactory): IList<IUser>;
var
Query : IDbQuery;
begin
Query := FDatabase.GetQuery();
Query.SQL := '
SELECT * FROM Users WHERE username = :username';
Query.Parameters.Add('
:username', Username);
Query.Open();
try
Result := TList<IUser>.Create();
for each Dataset
in Query.Results
do
begin
// User erzeugen mit Factory
User := UF.CreateUser(
Query['
IdUser']);
User.Username := Username;
User.LastLogon :=
Query['
LastLogon'];
...
Result.Add(User);
end;
finally
Query.Close();
end;
end;
Ein Service Locator ist ja auch eine Art Factory.
Allerdings kann ein Service Locator ALLE Arten von Objekten erzeugen,
während eine Factory auf eine bestimmte Gruppe von Objekten begrenzt ist.
Wenn man eine Factory wie oben im Beispiel übergibt ("injected"), dann bleibt der Code
weiterhin testbar und sauber.