Design mode, description with Delphi -> Visitor mode

zhaozj2021-02-08  224

Visitor mode

origin

The Visitor mode in Delphi has expanded in the basic Visitor mode. For more information on Visitor mode, please refer to [Gam , Pages 331..344].

purpose

Indicates an operation of neutralizing elements that acts on a target structure. It allows you to define new operations for these elements without changing the class of each element.

[GAM , Page 331].

motivation

Consider an object-oriented modeling tool, such as 'Rational Rose, ModelMaker', which represents a model as a member of the class and class.

A number of operating membership functions are provided on the modeling tool, such as all members of the list class, generated class code frame, reverse engineering, etc.

Most of these operations do different operations for different members. It divides the member into a field (Methods),

Properties. Because we must establish a class specifically handled fields, dedicated to the class of Methods, and the like. The collection of members classes is of course dependent on the compiled language. But there is no change in a given language.

A framework of some member classes is shown as shown. The problem is generated, if I divide all these operations to different member classes,

It will cause the entire system to be difficult to understand, modify, and maintain. Put the class code generation with the class member will be confusing. Some classes that should be recompiled when adding new operations (at least all related systems). There is a way: you may independently add a new action and this member class is independent of the operation acting on it.

To achieve the above two goals, we can pack each class in an independent object (called Visitor)

And passed this object to the current member when traversing a list of members. When a member 'accepts' access, the member sends a request to the visitor containing its own information. The member is requested from itself as a parameter. Visitors perform these operations.

For example: A code generator that does not use the visitor may pass abstract ways of the member class: Tmember.WriteInterfaceCode (Output: TStream) generates code. Each member calls WriteInterfaceCode to generate an appropriate output code. If you generate a code by visitor, a TinterfaceCodeVisitor object is created and the parameter is called on the member list as an Acceptvisitor method to access the object. Each member will call the Visitor: A field will call the visitor's Visitfield method, and a method calls the VisitMethod method. This way, the previous class TField's WriteInterfaceCode operation is now a Visitfield operation for TinterfaceCodevisitor.

In order to make the visitor not only only code generation, we need the visitors of all the members lists with an abstract parent class Tmembervisitor. Tmembervisitor must define a method for each member. A application that needs to output members to HTML format will define new subclasses of Tmembervisitor and no longer need to increase the code associated with specific applications in the member class. Visitor mode Pack each operation in a related Visitor

Using Visitor mode, you must define two levels: a one of the elements that should be accepted (TMEMBER Hierarchy) The other is defined to the elements (TMEMBERVISITOR Hierarchy). Add a new subclass when adding a new operation. I may simply define a new Tmembervisitor subclass to add new features.

application

The following code demonstrates the application of the Visitor mode of the class Tmember described above

Type

Tmember = Class (TOBJECT)

public

Procedure Acceptmembervisitor (Visitor: Tmembervisitor); Virtual; End;

Tfield = Class (TMEMBER)

public

Procedure Acceptmembervisitor (Visitor: Tmembervisitor); OVERRIDE;

END;

TMETHOD = Class (TMEMBER)

public

Procedure Acceptmembervisitor (Visitor: Tmembervisitor); OVERRIDE;

END;

TPROPERTY = Class (TMEMBER)

public

Procedure Acceptmembervisitor (Visitor: Tmembervisitor); OVERRIDE;

END;

Tmembervisitor = Class (TOBJECT)

public

Procedure Visitfield (Instance: Tfield); Virtual;

Procedure Visitmember (Instance: Tmember); Virtual;

Procedure Visitmeth (Instance: TMethod); Virtual;

Procedure VisitProperty (Instance: tproperty); virtual;

END;

IMPLEMENTATION

{Tmember}

Begin

Visitor.Visitmember (Self);

END;

{Tfield}

Procedure Tfield.Acceptmembervisitor (Visitor: Tmembervisitor);

Begin

END;

{TMETHOD}

Procedure Tmethod.AcceptMembervisitor (Visitor: Tmembervisitor);

Begin

Visitor.visitmethod (Self);

END;

{Tproperty}

Procedure tproperty.acceptmembervisitor (Visitor: Tmembervisitor);

Begin

Visitor.visitProperty (Self);

END;

{Tmembervisitor}

Procedure Tmembervisitor.visitfield (Instance: Tfield);

Begin

END;

Procedure Tmembervisitor.Visitmember (Instance: Tmember);

Begin

END;

Procedure Tmembervisitor.Visitmethod (Instance: TMethod);

Begin

END;

Procedure Tmembervisitor.visitProperty (Instance: tproperty);

Begin

END;

Description:

· Tmember, Tfield, TMethod and TProperty implement an Acceptmembervisitor method. These methods are embedded in the mode.

· The Tmembervisitor class implements a method such as Visitmember, Visitfield, etc. Tmembervisitor is an abstract class whose approach is achieved by specific subclasses.

Below is an implementation of a simple code generator.

Code introduction:

• TcodeGenerationVisitor is a visitor for code generator for implementing members.

· Visitors define a context-related properties: Output: TtextStream,

· It must be determined before the Visitxxx call, such as: DrawingVisitor typically requires a context including Canvas to support draw operations. The context gives a code generator before traversing the entire Member. · Code generator will complete all code of the generated class

To really understand the Visitor mode, you can perform this example and further learn the double dispatcher: Accept / Visit.

UNIT CODEGENERATORS;

Interface

Uses Classes, TextStreams;

Type

TcodeGenerator = Class (TOBJECT)

public

Procedure generate (MEMBERS: TLIST; OUTPUT: TTEXTSTREAM);

END;

IMPLEMENTATION

Uses members;

Type

TcodeGenerationVisitor = Class (Tmembervisitor)

Private

Foutput: TTEXTSTREAM;

public

Procedure: Tfield; Override;

Procedure Visitmethod (Instance: TMethod); OVERRIDE;

Procedure Visitproperty (Instance: tproperty); OVERRIDE;

Property Output: TtextStream Read Foutput Write Foutput;

END;

{TcodeGenerationVisitor}

Procedure TcodeGenerationVisitor.visitfield (Instance: tfield);

Begin

Output.writelnfmt ('% s:% s;', [instance.name, instance.dataname]);

END;

Procedure TcodeGenerationVisitor.Visitmethod (Instance: TMethod);

VAR

MKSTR, DTSTR: STRING;

Begin

Case Instance.Methodkind of

MKConstructor: mkstr: = 'constructor';

MKDESTRUCTOR: MKSTR: = 'DESTRUCTOR';

MkProcedure: MKSTR: = 'procadure';

MKFUNTION: MKSTR: = 'Function';

END;

IF instance.methodkind = mkfunction then

DTSTR: = ':' instance.dataname

Else

DTSTR: = '';

The {code is incomplete, it is now sufficient to demonstrate the TMETHOD code generation}

Output.writelnfmt ('% s% s% s% s;'

[MKSTR, Instance.Name, Instance.Parameters, DTSTR]);

END;

Procedure TcodeGenerationVisitor.visitProperty (Instance: tproperty);

Begin

Output.writelnfmt ('Property% S:% s ied% s write% s; "

Instance.Name, Instance.Dataname,

Instance.readspecifier, instance.writespecifier]);

End; {tcodegenerator}

Procedure tcodegenerator.generate (MEMBERS: TLIST; OUTPUT: TTEXTSTREAM);

VAR

I: integer;

Begin

{Write class definition}

Output.writeLine ('Tsample = Class (TOBJECT)');

{it is good! Add to code generator Accessor}

Visitor: = tcodegenerationvisitor.create;

Try

{Remember to provide context for access to better access the Visitxxx method. }

For i: = 0 to Members.count - 1 DO

{Code specific segment, good things happen}

Tmember (MEMBERS [I]). Acceptmembervisitor (Visitor);

Finally

Visitor.free;

END;

The code generation of the {class member is completed.

Output.writeLine ('end;');

END;

Delphi instance

Be organized

// A lot from "design mode",

转载请注明原文地址:https://www.9cbs.com/read-3042.html

New Post(0)