I guess this should be an easy one cause I must be doing something wrong.
this is my code, I'm trying to do a Strategy pattern in Delphi:
unit Pattern;
interface
type
TContext = class;
IStrategy = interface
function Move(c: TContext): integer;
end;
TStrategy1 = class(TInterfacedObject, IStrategy)
public
function Move(c: TContext): integer;
end;
TStrategy2 = class(TInterfacedObject, IStrategy)
public
function Move(c: TContext): integer;
end;
TContext = class
const
START = 5;
private
FStrategy: IStrategy;
public
FCounter: integer;
constructor Create;
function Algorithm(): integer;
procedure SwitchStrategy();
end;
implementation
{ TStrategy1 }
function TStrategy1.Move(c: TContext): integer;
begin
c.FCounte开发者_开发问答r := c.FCounter + 1;
Result := c.FCounter;
end;
{ TStrategy2 }
function TStrategy2.Move(c: TContext): integer;
begin
c.FCounter := c.FCounter - 1;
Result := c.FCounter;
end;
{ TContext }
function TContext.Algorithm: integer;
begin
Result := FStrategy.Move(Self)
end;
constructor TContext.Create;
begin
FCounter := 5;
FStrategy := TStrategy1.Create();
end;
procedure TContext.SwitchStrategy;
begin
if FStrategy is TStrategy1 then
FStrategy := TStrategy2.Create()
else
FStrategy := TStrategy1.Create();
end;
end.
And the if FStrategy is TStrategy1 then is giving me: Operator not applicable to this operand type. What am I doing wrong here cause this should work as I understand from a lot of Delphi language references?
You have omitted the GUID from your interface. is
can't work without it.
Edit: On second glance, it still won't work. You can't use is
to test an interface reference for its implementing object typein Delphi (well, not directly, anyway). You should change your design. For example, you could either alter the interface or add another interface to return a description of the implementation.
You could make this work by adding the IID/GUID as Craig states, and then changing SwitchStrategy
to:
procedure TContext.SwitchStrategy;
begin
if (FStrategy as TObject) is TStrategy1 then
FStrategy := TStrategy2.Create()
else
FStrategy := TStrategy1.Create();
end;
This only works with more modern versions of Delphi. I think Delphi 2010 was where the ability to cast an interface to its implementing object was added.
However, I'd be inclined to avoid this solution and go for something like this:
type
IStrategy = interface
function Move(c: TContext): integer;
function Switch: IStrategy;
end;
TStrategy1 = class(TInterfacedObject, IStrategy)
public
function Move(c: TContext): integer;
function Switch: IStrategy;
end;
TStrategy2 = class(TInterfacedObject, IStrategy)
public
function Move(c: TContext): integer;
function Switch: IStrategy;
end;
function TStrategy1.Switch: IStrategy;
begin
Result := TStrategy2.Create;
end;
function TStrategy2.Switch: IStrategy;
begin
Result := TStrategy1.Create;
end;
procedure TContext.SwitchStrategy;
begin
FStrategy := FStrategy.Switch;
end;
When you find yourself asking an object what type it is, that's usually indicative of a design weakness.
精彩评论