unit Patterns.Specifications;
interface
uses
System.SysUtils;
type
ISpecification =
interface
[ '
{664ED0AE-42AF-4B5A-9A9F-D6C7565D995C}' ]
function IsSatisfiedBy(
const candidate: TObject ): Boolean;
function &
And( other: ISpecification ): ISpecification;
function &
Or( other: ISpecification ): ISpecification;
function &
Not( ): ISpecification;
end;
TCompositeSpecification =
class abstract( TInterfacedObject, ISpecification )
public
function IsSatisfiedBy(
const candidate: TObject ): Boolean;
virtual;
abstract;
function &
And( other: ISpecification ): ISpecification;
function &
Or( other: ISpecification ): ISpecification;
function &
Not( ): ISpecification;
end;
TAndSpecification =
class( TCompositeSpecification )
private
FLeft, FRight: ISpecification;
public
constructor Create( Left, Right: ISpecification );
function IsSatisfiedBy(
const candidate: TObject ): Boolean;
override;
end;
TOrSpecification =
class( TCompositeSpecification )
private
FLeft, FRight: ISpecification;
public
constructor Create( Left, Right: ISpecification );
function IsSatisfiedBy(
const candidate: TObject ): Boolean;
override;
end;
TNotSpecification =
class( TCompositeSpecification )
private
FOther: ISpecification;
public
constructor Create( other: ISpecification );
function IsSatisfiedBy(
const candidate: TObject ): Boolean;
override;
end;
TDelegatedSpecification =
class( TCompositeSpecification )
private
FDelegate: TPredicate<TObject>;
public
constructor Create( ADelegate: TPredicate<TObject> );
function IsSatisfiedBy(
const candidate: TObject ): Boolean;
override;
end;
TDelegatedSpecification<T:
class> =
class( TDelegatedSpecification )
public
constructor Create( ADelegate: TPredicate<T> );
end;
implementation
{ TCompositeSpecification }
function TCompositeSpecification.&
And( other: ISpecification ): ISpecification;
begin
Result := TAndSpecification.Create( self, other );
end;
function TCompositeSpecification.&
Not: ISpecification;
begin
Result := TNotSpecification.Create( self );
end;
function TCompositeSpecification.&
Or( other: ISpecification ): ISpecification;
begin
Result := TOrSpecification.Create( self, other );
end;
{ TAndSpecification }
constructor TAndSpecification.Create( Left, Right: ISpecification );
begin
inherited Create;
FLeft := Left;
FRight := Right;
end;
function TAndSpecification.IsSatisfiedBy(
const candidate: TObject ): Boolean;
begin
Result := FLeft.IsSatisfiedBy( candidate )
and FRight.IsSatisfiedBy( candidate );
end;
{ TOrSpecification }
constructor TOrSpecification.Create( Left, Right: ISpecification );
begin
inherited Create;
FLeft := Left;
FRight := Right;
end;
function TOrSpecification.IsSatisfiedBy(
const candidate: TObject ): Boolean;
begin
Result := FLeft.IsSatisfiedBy( candidate )
or FRight.IsSatisfiedBy( candidate );
end;
{ TNotSpecification }
constructor TNotSpecification.Create( other: ISpecification );
begin
inherited Create;
FOther := other;
end;
function TNotSpecification.IsSatisfiedBy(
const candidate: TObject ): Boolean;
begin
Result :=
not FOther.IsSatisfiedBy( candidate );
end;
{ TDelegatedSpecification }
constructor TDelegatedSpecification.Create( ADelegate: TPredicate<TObject> );
begin
inherited Create( );
FDelegate := ADelegate;
end;
function TDelegatedSpecification.IsSatisfiedBy(
const candidate: TObject ): Boolean;
begin
Result := FDelegate( candidate );
end;
{ TDelegatedSpecification<T> }
constructor TDelegatedSpecification<T>.Create( ADelegate: TPredicate<T> );
begin
inherited Create(
function( o: TObject ): Boolean
begin
Result := true
{} and ( o
is T )
{} and ADelegate( o
as T );
end );
end;
end.