 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Sherlyn Guest
|
Posted: Fri Sep 08, 2006 2:35 pm Post subject: Can Visitor Return Result ? |
|
|
Hi Everyone,
According to GOF Design Pattern books, the visitor pattern doesn't return
any result in Visit method. But if my visitor method doing some calculation
based on the parameter pass in, and the result is needed by other class, how
do I return the value after visit method is invoked?
My example below will convert a numeric value to string. I have some
ValueType classes (eg: TIntegerValue & TCurrencyValue), these classes
implements IVisitable interface. I then have a Visitor class (eg:
TVisitorValue) visiting each ValueType classes. The visitor class has visit
methods processing ValueType instances. The result calculated in the visitor
methods may used by others.
I have some possible solutions. I am glad if someone suggest a better
solution.
Thank you very much.
Examples :
IVisitable = interface
procedure Accept(const aVisitor: IInterface);
IIntegerValue = interface
property Value: integer read GetValue;
end;
ICurrencyValue = interface
property Value: currency read GetValue;
end;
IVisitorValue = interface
procedure VisitIntegerValue(const aValue: IIntegerValue);
procedure VisitCurrencyValue(const aValue: ICurrencyValue);
end;
TIntegerValue = class(TInterfacedObject, IIntegerValue, IVisitable)
protected
procedure Accept(const aVisitor: IInterface);
function GetValue: integer;
procedure SetValue(const aValue: integer);
end;
TCurrencyValue = class(TInterfacedObject, ICurrencyValue, IVisitable)
protected
procedure Accept(const aVisitor: IInterface);
function GetValue: currency;
procedure SetValue(const aValue: currency);
end;
TVisitorValue = interface
private
FValue: IValueString;
protected
procedure VisitIntegerValue(const aValue: IIntegerValue);
procedure VisitCurrencyValue(const aValue: ICurrencyValue);
implementation
procedure TIntegerValue.Accept(const aVisitor: IInterface);
begin
(aVisitor as IVisitorValue).VisitIntegerValue(Self);
end;
procedure TCurrencyValue.Accept(const aVisitor: IInterface);
begin
(aVisitor as IVisitor.Value).VisitCurrencyValue(Self);
end;
procedure TVisitorValue.AfterConstruction;
begin
FValue := TValueString.Create;
end;
procedure TVisitorValue.VisitIntegerValue(const aValue: IIntegerValue);
begin
case aValue of
1: FValue.Value := 'One';
2: FValue.Value := 'Two';
end;
end;
procedure TVisitorValue.VisitCurrencyValue(const aValue: ICurrencyValue);
begin
if aValue = 123 then
FValue.Value := 'One Hundred and Twenty Three Dollar';
end;
Suggestion 1 - Visitor & Visitable classses return the result
=======================================
IVisitable = interface
function Accept(const aVisitor: IInterface): IInterface;
end;
IVisitorValue = interface
function VisitIntegerValue(const aValue: IIntegerValue): IInterface;
function VisitCurrencyValue(const aValue: ICurrencyValue): IInterface;
end;
function TIntegerValue.Accept(const aVisitor: IInterface): IInterface;
begin
Result := aVisitor.VisitIntegerValue(Self);
end;
Suggestion 2 - Access the result via Visitor class that publish the property
=================================================
IVisitable = interface
procedure Accept(const aVisitor: IInterface);
end;
IVisitorValue = interface
procedure VisitIntegerValue(const aValue: IIntegerValue);
procedure VisitCurrencyValue(const aValue: ICurrencyValue);
function GetValue: string;
property Value: string read GetValue;
end;
procedure TIntegerValue.Accept(const aVisitor: IInterface);
begin
Result := aVisitor.VisitIntegerValue(Self);
end;
Suggestion 3 - Cast the visitor instance and get the value
======================================
function TVisitorValue.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if IsEqualGUID(IID, IValueString) then begin
IValueString(Obj) := FValue;
Result := S_OK;
end else
Result := inherited QueryInterface(IID, Obj);
end;
var S: string;
begin
I := TIntegerValue.Create;
I.Value := 100;
V := TVisitorValue.Create;
(I as IVisitable).Accept(V);
S := (V as IValueString).Value;
end;
From,
Sherlyn |
|
| Back to top |
|
 |
Joanna Carter [TeamB] Guest
|
Posted: Fri Sep 08, 2006 4:09 pm Post subject: Re: Can Visitor Return Result ? |
|
|
"Sherlyn" <sherlyn (AT) estream (DOT) com.my> a écrit dans le message de news:
45013980 (AT) newsgroups (DOT) borland.com...
| According to GOF Design Pattern books, the visitor pattern doesn't return
| any result in Visit method. But if my visitor method doing some
calculation
| based on the parameter pass in, and the result is needed by other class,
how
| do I return the value after visit method is invoked?
|
| My example below will convert a numeric value to string. I have some
| ValueType classes (eg: TIntegerValue & TCurrencyValue), these classes
| implements IVisitable interface. I then have a Visitor class (eg:
| TVisitorValue) visiting each ValueType classes. The visitor class has
visit
| methods processing ValueType instances. The result calculated in the
visitor
| methods may used by others.
| Suggestion 2 - Access the result via Visitor class that publish the
property
| =================================================
| IVisitable = interface
| procedure Accept(const aVisitor: IInterface);
| end;
|
| IVisitorValue = interface
| procedure VisitIntegerValue(const aValue: IIntegerValue);
| procedure VisitCurrencyValue(const aValue: ICurrencyValue);
| function GetValue: string;
| property Value: string read GetValue;
| end;
|
| procedure TIntegerValue.Accept(const aVisitor: IInterface);
| begin
| Result := aVisitor.VisitIntegerValue(Self);
| end;
I think that there is a bit of copy/paste error here but this is really the
best idea, when corrected :-)
IValueVisitor = interface(IVisitor)
procedure VisitIntegerValue(const value: IIntegerValue);
procedure VisitCurrencyValue(const value: ICurrencyValue);
...
end;
TStringConvertValueVisitor = interface(IStringConvertValueVisitor)
private
fStringValue;
function GetStringValue: string
property StringValue: string read GetStringValue;
protected
procedure VisitIntegerValue(const value: IIntegerValue); override;
...
end;
implementation
function TStringConvertValueVisitor.GetStringValue: string
begin
Result := fStringValue;
end;
procedure TStringConvertValueVisitor.VisitIntegerValue(const value:
IIntegerValue);
begin
fStringValue := // result of conversion
end;
So you get code that does something like this :
var
visitor: IStringConvertValueVisitor;
convertedString: string;
begin
visitor = TStringValueVisitor.Create;
myIntValue.Accept(visitor);
convertedString := visitor.StringValue;
...
end;
Joanna
--
Joanna Carter [TeamB]
Consultant Software Engineer |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|