Hier ein möglicher Lösungsvorschlag zum Aufbrechen des Kreises, ganz objektorientiert und ohne Verwendung von Interfaces (was sicher auch eine valide Lösung wäre). Statt direkt auf eine
TPlayer-Instanz zuzugreifen, wird hier eine abstrakte Player-Klasse eingeführt.
Delphi-Quellcode:
unit Blocks;
interface
type
TBlock =
class(TObject)
end;
TAbstractPlayer =
class abstract
public
procedure DoWithBlock(ABlock: TBlock);
virtual;
abstract;
end;
TActionBlock =
class(TBlock)
public
procedure OnAction(APlayer: TAbstractPlayer);
end;
implementation
procedure TActionBlock.OnAction(APlayer: TAbstractPlayer);
begin
APlayer.DoWithBlock(Self);
end;
end.
Die
Maps-
Unit ist hier nicht relevant, da sie nur indirekt an dem Kreis beteiligt war und nicht selber einen gebildet hat.
Eigentlich würde man
TPlayer direkt von
TAbstractPlayer ableiten. Da aber
TPlayer schon von
TEntity abgeleitet wird, schalten wir eine neue Adapter-Klasse dazwischen.
Delphi-Quellcode:
unit Entity;
interface
uses
Map, Blocks;
type
TEntity =
class
end;
type
TPlayer =
class(TEntity)
private
FPlayerAdapter: TAbstractPlayer;
public
constructor Create;
destructor Destroy;
override;
procedure DoWithBlock(ABlock: TBlock);
end;
implementation
type
TPlayerAdapter =
class(TAbstractPlayer)
private
FPlayer: TPlayer;
public
constructor Create(APlayer: TPlayer);
procedure DoWithBlock(ABlock: TBlock);
override;
end;
constructor TPlayerAdapter.Create(APlayer: TPlayer);
begin
inherited Create;
FPlayer := APlayer;
end;
procedure TPlayerAdapter.DoWithBlock(ABlock: TBlock);
begin
FPlayer.DoWithBlock(ABlock);
end;
constructor TPlayer.Create;
begin
inherited Create;
FPlayerAdapter := TPlayerAdapter.Create(Self);
end;
destructor TPlayer.Destroy;
begin
FPlayerAdapter.Free;
inherited Destroy;
end;
procedure TPlayer.DoWithBlock(ABlock: TBlock);
begin
end;
end.
Natürlich muss das noch an die tatsächlichen Gegebenheiten angepasst werden, aber das Prinzip sollte erkennbar sein.