unit Myc.Data.Keyword; interface uses System.SysUtils, System.Classes, System.Generics.Collections, System.SyncObjs; type // The runtime representation of an interned keyword IKeyword = interface(IInterface) function GetName: string; property Name: string read GetName; end; // Factory and registry for all keywords (Flyweight Pattern) TKeywordRegistry = record strict private type TKeyword = class(TInterfacedObject, IKeyword) private FName: string; function GetName: string; public constructor Create(const AName: string); end; strict private class var FLock: TSpinLock; class var FRegistry: TDictionary; class constructor Create; class destructor Destroy; public // Gets or creates the interned keyword for the given name. class function Intern(const AName: string): IKeyword; static; end; implementation { TKeywordRegistry.TKeyword } constructor TKeywordRegistry.TKeyword.Create(const AName: string); begin inherited Create; FName := AName; end; function TKeywordRegistry.TKeyword.GetName: string; begin Result := FName; end; { TKeywordRegistry } class constructor TKeywordRegistry.Create; begin FLock := TSpinLock.Create(false); FRegistry := TDictionary.Create; end; class destructor TKeywordRegistry.Destroy; begin FRegistry.Free; end; class function TKeywordRegistry.Intern(const AName: string): IKeyword; begin FLock.Enter; try if not FRegistry.TryGetValue(AName, Result) then begin Result := TKeyword.Create(AName); FRegistry.Add(AName, Result); end; finally FLock.Exit; end; end; end.