type
TCache =
class
private
FMaxSize: Integer;
FCacheDict: TDictionary<Integer, TObject>;
FCacheIDs: TList<Integer>;
procedure Renew(ID: Integer);
procedure CleanCache;
function GetCurrentNumberOfElements: Integer;
function GetSize: Integer;
public
constructor Create (MaxSize : Integer);
destructor Destroy;
override;
function Contains (ID : Integer) : Boolean;
function Get (ID : Integer) : TObject;
procedure Put (ID : Integer; Item : TObject);
procedure Remove(ID : Integer);
property MaxSize : Integer
Read GetSize;
property CurrentNumberOfElements : Integer
Read GetCurrentNumberOfElements;
end;
implementation
{ TCache }
procedure TCache.CleanCache;
var i: Integer;
begin
for i := FCacheIDs.Count-1
downto FMaxSize
do
begin
FCacheDict.Remove(FCacheIDs[i]);
FCacheIDs.Delete(i);
end;
end;
function TCache.
Contains(ID: Integer): Boolean;
begin
Result := FCacheDict.ContainsKey(ID);
end;
constructor TCache.Create(MaxSize: Integer);
begin
inherited Create;
FMaxSize := MaxSize;
FCacheDict := TDictionary<Integer, TObject>.Create;
FCacheIDs := TList<Integer>.Create;
end;
destructor TCache.Destroy;
begin
FreeAndNil(FCacheDict);
FreeAndNil(FCacheIDs);
inherited;
end;
function TCache.Get(ID: Integer): TObject;
begin
if Contains(ID)
then
begin
Result := FCacheDict[ID];
Renew(ID);
end
else
raise EListError.CreateFmt('
Das Element mit der ID %d ist nicht im Cache enthalten!', [ID]);
end;
function TCache.GetCurrentNumberOfElements: Integer;
begin
Result := FCacheDict.Count;
end;
function TCache.GetSize: Integer;
begin
Result := FMaxSize;
end;
procedure TCache.Put(ID: Integer; Item: TObject);
begin
if not Contains(ID)
then
begin
FCacheIDs.Insert(0, ID);
FCacheDict.Add(ID, Item);
CleanCache();
end
else
Renew(ID);
// Evtl eher ne Exception? Ist Geschmackssache denke ich.
end;
procedure TCache.Remove(ID: Integer);
begin
FCacheIDs.Remove(ID);
FCacheDict.Remove(ID);
end;
procedure TCache.Renew(ID: Integer);
var OldIndex: Integer;
begin
OldIndex := FCacheIDs.IndexOf(ID);
if OldIndex <> -1
then
FCacheIDs.Move(OldIndex, 0);
end;