BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Can Visitor Return Result ?

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design
View previous topic :: View next topic  
Author Message
Sherlyn
Guest





PostPosted: Fri Sep 08, 2006 2:35 pm    Post subject: Can Visitor Return Result ? Reply with quote



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





PostPosted: Fri Sep 08, 2006 4:09 pm    Post subject: Re: Can Visitor Return Result ? Reply with quote



"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
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.