|
In object-oriented programming and software engineering, the visitor design pattern is a way of separating an algorithm from an object structure. A practical result of this separation is the ability to add new operations to existing object structures without modifying those structures. Object-oriented programming (OOP) is a programming paradigm that uses objects and their interactions to design applications and computer programs. ...
Software engineering (SE) is the application of a systematic, disciplined, quantifiable approach to the development, operation, and maintenance of software. ...
In software engineering, a design pattern is a general repeatable solution to a commonly occurring problem in software design. ...
In mathematics, computing, linguistics, and related disciplines, an algorithm is a finite list of well-defined instructions for accomplishing some task that, given an initial state, will terminate in a defined end-state. ...
The idea is to use a structure of element classes, each of which has an accept method that takes a visitor object as an argument. Visitor is an interface that has a visit() method for each element class. The accept() method of an element class calls back the visit() method for its class. Separate concrete visitor classes can then be written that perform some particular operations. An interface defines the communication boundary between two entities, such as a piece of software, a hardware device, or a user. ...
One of these visit() methods of a concrete visitor can be thought of as methods not of a single class, but rather methods of a pair of classes: the concrete visitor and the particular element class. Thus the visitor pattern simulates double dispatch in a conventional single-dispatch object-oriented language such as Java, Smalltalk, and C++. For an explanation of how double dispatch differs from function overloading, see Double dispatch is more than function overloading in the double dispatch article. In the Java language, two techniques have been documented which use reflection to simplify the mechanics of double dispatch simulation in the visitor pattern: getting rid of accept() methods, and getting rid of extra visit() methods. Double dispatch is a mechanism that dispatches a function call to different concrete functions depending on the runtime types of multiple objects involved in the call. ...
Object-oriented programming (OOP) is a computer programming paradigm in which a software system is modeled as a set of objects that interact with each other. ...
âJava languageâ redirects here. ...
For other uses, see Small talk. ...
C++ (pronounced see plus plus, IPA: ) is a general-purpose programming language with high-level and low-level capabilities. ...
In computer science, polymorphism is the idea of allowing the same code to be used with different types, resulting in more general and abstract implementations. ...
Double dispatch is a mechanism that dispatches a function call to different concrete functions depending on the runtime types of multiple objects involved in the call. ...
Computational reflection (sometimes shortened to reflection), in the context of computer science, is the ability of a program to observe and possibly modify its structure and behavior. ...
The visitor pattern also specifies how iteration occurs over the object structure. In the simplest version, where each algorithm needs to iterate in the same way, the accept() method of a container element, in addition to calling back the visit() method of the visitor, also passes the visitor object to the accept() method of all its constituent child elements. Because the Visitor object has one principal function (manifested in a plurality of specialized methods) and that function is called visit(), the Visitor can be readily identified as a potential function object or functor. Likewise, the accept() function can be identified as a function applicator, a mapper, which knows how to traverse a particular type of object and apply a function to its elements. The Common Lisp example found on the visitor pattern examples page shows an implementation of the same behavior as the other examples, using functions. It's noteworthy that although Common Lisp has one of the few object systems that support multiple dispatch, the first part of the example does not rely on multiple dispatch. The use of multiple dispatch is introduced in a second example; yet the framework remains the same. Lisp's object system with its multiple dispatch does not replace the Visitor pattern, but merely provides a more concise implementation of it in which the pattern all but disappears. A function object, often called a functor or functionoid, is a computer programming construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax. ...
Did somebody just say functor? In category theory, a functor is a special type of mapping between categories. ...
Common Lisp, commonly abbreviated CL, is a dialect of the Lisp programming language, published in ANSI standard X3. ...
Multiple dispatch or multimethods is the feature of some object-oriented programming languages in which a function or method can be specialized on the type of more than one of its arguments. ...
Example
The following example is an example in the Java programming language: âJava languageâ redirects here. ...
interface Visitor { void visit(Wheel wheel); void visit(Engine engine); void visit(Body body); void visit(Car car); } interface Visitable { void accept(Visitor visitor); } class Wheel implements Visitable { private String name; Wheel(String name) { this.name = name; } String getName() { return this.name; } public void accept(Visitor visitor) { visitor.visit(this); } } class Engine implements Visitable{ public void accept(Visitor visitor) { visitor.visit(this); } } class Body implements Visitable{ public void accept(Visitor visitor) { visitor.visit(this); } } class Car implements Visitable { private Engine engine = new Engine(); private Body body = new Body(); private Wheel[] wheels = { new Wheel("front left"), new Wheel("front right"), new Wheel("back left") , new Wheel("back right") }; public Engine getEngine() { return this.engine; } public Body getBody() { return this.body; } public Wheel[] getWheels() { return this.wheels; } public void accept(Visitor visitor) { visitor.visit(this); engine.accept(visitor); body.accept(visitor); for(Wheel wheel : wheels) { wheel.accept(visitor); } } } class PrintVisitor implements Visitor { public void visit(Wheel wheel) { System.out.println("Visiting "+ wheel.getName() + " wheel"); } public void visit(Engine engine) { System.out.println("Visiting engine"); } public void visit(Body body) { System.out.println("Visiting body"); } public void visit(Car car) { System.out.println("Visiting car"); } } class DoVisitor implements Visitor { public void visit(Wheel wheel) { System.out.println("Steering my wheel"); } public void visit(Engine engine) { System.out.println("Starting my engine"); } public void visit(Body body) { System.out.println("Moving my body"); } public void visit(Car car) { System.out.println("Vroom!"); } } public class VisitorDemo { static public void main(String[] args){ Car car = new Car(); Visitor visitor = new PrintVisitor(); Visitor doVisitor = new DoVisitor(); car.accept(visitor); car.accept(doVisitor); } } The following example is an example in the C++ programming language: For a WikiBook on programming with C++, see Wikibooks: C++ Programming. ...
/************************************************************************ /* Device.h file /************************************************************************/ #ifndef DEVICE_HEADER_FILE #define DEVICE_HEADER_FILE #include <iostream> #include <vector> #include <string> class VisitorInterface; class baseComponent { public: baseComponent(const std::string& name, float price = 0.0f) : m_name(name), m_price(price) {} void virtual Accept(VisitorInterface&) = 0; std::string m_name; float m_price; }; ////////////////////////////////////////////////////////////////////////// class Tire : public baseComponent { public: Tire(const std::string& name) : baseComponent(name) {} Tire(const std::string& name, float price) : baseComponent(name, price) {} void virtual Accept(VisitorInterface&); }; ////////////////////////////////////////////////////////////////////////// class Engine: public baseComponent { public: Engine(std::string str):baseComponent(str){} Engine(std::string str,int price):baseComponent(str,price){} void virtual Accept(VisitorInterface&); }; ////////////////////////////////////////////////////////////////////////// class Body: public baseComponent { public: Body(std::string str) : baseComponent(str){} Body(std::string str, int price) : baseComponent(str, price){} void virtual Accept(VisitorInterface&); }; ////////////////////////////////////////////////////////////////////////// class Car: public baseComponent { public: Car(const std::string& str); Car(const std::string& str,int p1,int p2,int p3,int p4,int p5,int p6); ~Car(); void virtual Accept(VisitorInterface&); private: std::vector<baseComponent*> m_components; std::vector<baseComponent*>::iterator m_iter; }; #endif /************************************************************************ /* Device.cpp file /************************************************************************/ #include "Visitor.h" #include "Device.h" ////////////////////////////////////////////////////////////////////////// void Tire::Accept(VisitorInterface& visitor) { visitor.Visit(*this); } ////////////////////////////////////////////////////////////////////////// void Engine::Accept(VisitorInterface& visitor) { visitor.Visit(*this); } ////////////////////////////////////////////////////////////////////////// void Body::Accept(VisitorInterface& visitor) { visitor.Visit(*this); } ////////////////////////////////////////////////////////////////////////// Car::Car(const std::string& str) : baseComponent(str) { m_components.push_back(new Tire("Front left")); m_components.push_back(new Tire("Front right")); m_components.push_back(new Tire("Rear left")); m_components.push_back(new Tire("Rear right")); m_components.push_back(new Engine("V12 model Engine")); m_components.push_back(new Body("Spaceship alloy Body")); } Car::Car(const std::string &str,int p1,int p2,int p3,int p4,int p5,int p6) : baseComponent(str) { m_components.push_back(new Tire("Front left", p1)); m_components.push_back(new Tire("Front right", p2)); m_components.push_back(new Tire("Rear left", p3)); m_components.push_back(new Tire("Rear right", p4)); m_components.push_back(new Engine("V12 model Engine", p5)); m_components.push_back(new Body("Spaceship alloy Body", p6)); } Car::~Car() { for(m_iter = m_components.begin(); m_iter != m_components.end(); ++m_iter){ if(NULL != (*m_iter)){ delete (*m_iter); (*m_iter) = NULL; } } m_components.clear(); } void Car::Accept(VisitorInterface& visitor) { visitor.Visit(*this); for(m_iter = m_components.begin(); m_iter != m_components.end(); ++m_iter){ (*m_iter)->Accept(visitor); } } /************************************************************************ /* Visitor.h file /************************************************************************/ #ifndef VISITOR_HEADER_FILE #define VISITOR_HEADER_FILE #include "Device.h" #include <iostream> ////////////////////////////////////////////////////////////////////////// class VisitorInterface { public: void virtual Visit(Tire&) = 0; void virtual Visit(Engine&) = 0; void virtual Visit(Body&) = 0; void virtual Visit(Car&) = 0; }; ////////////////////////////////////////////////////////////////////////// class PrintVisitor : public VisitorInterface { public: void virtual Visit(Tire&); void virtual Visit(Engine&); void virtual Visit(Body&); void virtual Visit(Car&); }; ////////////////////////////////////////////////////////////////////////// class DoVisitor : public VisitorInterface { public: void virtual Visit(Tire&); void virtual Visit(Engine&); void virtual Visit(Body&); void virtual Visit(Car&); }; ////////////////////////////////////////////////////////////////////////// class PriceVisitor : public VisitorInterface { public: void virtual Visit(Tire&); void virtual Visit(Engine&); void virtual Visit(Body&); void virtual Visit(Car&); float GetPrice(){ std::cout << "Total price for this car is " << m_nTotalPrice << std::endl; return m_nTotalPrice; } private: float m_nTotalPrice; }; #endif /************************************************************************ /* Visitor.cpp file /************************************************************************/ #include "Visitor.h" ////////////////////////////////////////////////////////////////////////// void PrintVisitor::Visit(Tire& tire) { std::cout << "Visiting " << tire.m_name << " Tire" << std::endl; } void PrintVisitor::Visit(Body& body) { std::cout << "Visiting " << body.m_name << std::endl; } void PrintVisitor::Visit(Engine& engine) { std::cout << "Visiting " << engine.m_name << std::endl; } void PrintVisitor::Visit(Car& car) { std::cout << "Visiting " << car.m_name << std::endl; } ////////////////////////////////////////////////////////////////////////// void DoVisitor::Visit(Tire& tire) { std::cout << "Inflating tire: " << tire.m_name << std::endl; } void DoVisitor::Visit(Body& body) { std::cout << "Move the car body" << std::endl; } void DoVisitor::Visit(Engine& engine) { std::cout << "Starting my engine" << std::endl; } void DoVisitor::Visit(Car& car) { std::cout << "Vroom!" << std::endl; } ////////////////////////////////////////////////////////////////////////// void PriceVisitor::Visit(Tire& tire) { m_nTotalPrice += tire.m_price; } void PriceVisitor::Visit(Body& body) { m_nTotalPrice += body.m_price; } void PriceVisitor::Visit(Engine& engine) { m_nTotalPrice += engine.m_price; } void PriceVisitor::Visit(Car& car) { m_nTotalPrice = 0; } /************************************************************************ /* VisitorTutorial.cpp : Defines the entry point for the console application. /************************************************************************/ #include "Device.h" #include "Visitor.h" #include <conio.h> int _tmain(int argc, _TCHAR* argv[]) { Car *car = new Car("Mustang"); Car *carValued = new Car("Ford", 50, 50, 50, 50, 200, 300); VisitorInterface *visitor = new PrintVisitor(); VisitorInterface *doVisitor = new DoVisitor(); VisitorInterface *priceVisitor = new PriceVisitor(); car->Accept(*visitor); car->Accept(*doVisitor); car->Accept(*priceVisitor); dynamic_cast<PriceVisitor*>(priceVisitor)->GetPrice(); carValued->Accept(*priceVisitor); dynamic_cast<PriceVisitor*>(priceVisitor)->GetPrice(); delete car; delete visitor; delete doVisitor; delete priceVisitor; getch(); return 0; } Image File history File links Broom_icon. ...
State Aside from potentially improving separation of concerns, the visitor pattern has an additional advantage over simply calling a polymorphic method: a visitor object can have state. This is extremely useful in many cases where the action performed on the object depends on previous such actions. In computer science, separation of concerns (SoC) is the process of breaking a program into distinct features that overlap in functionality as little as possible. ...
An example of this is a pretty-printer in a programming language implementation (such as a compiler or interpreter). Such a pretty-printer object (implemented as a visitor, in this example), will visit nodes in a data structure that represents a parsed and processed program. The pretty-printer will then generate a textual representation of the program tree. In order to make the representation human readable, the pretty-printer should properly indent program statements and expressions. The current indentation level can then be tracked by the visitor as its state, correctly applying encapsulation, whereas in a simple polymorphic method invocation, the indentation level would have to be exposed as a parameter and the caller would rely on the method implementation to use and propagate this parameter correctly. To prettyprint (or pretty-print) is to make something, commonly some printed material, appear more appealing to the human eye. ...
A programming language is an artificial language that can be used to control the behavior of a machine, particularly a computer. ...
A diagram of the operation of a typical multi-language, multi-target compiler. ...
An interpreter is a computer program that executes other programs. ...
See also Double dispatch is a mechanism that dispatches a function call to different concrete functions depending on the runtime types of multiple objects involved in the call. ...
Multiple dispatch or multimethods is the feature of some object-oriented programming languages in which a function or method can be specialized on the type of more than one of its arguments. ...
This does not cite any references or sources. ...
In software engineering, the hierarchial visitor pattern is one of design patterns that intend to provide a way to visit every node in the hierarchical data structure such as a tree. ...
In computer programming, the strategy pattern is a particular software design pattern, whereby algorithms can be selected on-the-fly at runtime. ...
External links | Design patterns in Design Patterns | Creational: Abstract factory • Builder • Factory • Prototype • Singleton Known colloquially as Uncle Bob, Robert Cecil Martin has been a software professional since 1970 and an international software consultant since 1990. ...
Bertrand Meyer (born 1950 in France) developed the Eiffel programming language, and is an author, academic and consultant in the field of computer languages. ...
In software engineering, a design pattern is a general repeatable solution to a commonly occurring problem in software design. ...
This article is about the book by Gamma et al. ...
A software design pattern, the Abstract Factory Pattern provides a way to encapsulate a group of individual factories that have a common theme. ...
Oftentimes, builder pattern builds Composite pattern, a structure pattern. ...
The factory method pattern is an object-oriented design pattern. ...
A prototype pattern is a creational design pattern used in software development when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects. ...
In software engineering, the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object. ...
Structural: Adapter • Bridge • Composite • Decorator • Façade • Flyweight • Proxy In computer programming, the adapter design pattern (often referred to as the wrapper pattern or simply a wrapper) adapts one interface for a class into one that a client expects. ...
The bridge pattern is a design pattern used in software engineering which is meant to decouple an abstraction from its implementation so that the two can vary independently (Gamma et. ...
This does not cite any references or sources. ...
In object-oriented programming, a decorator pattern is a design pattern. ...
The façade pattern is an object-oriented design pattern. ...
Flyweight is a software design pattern. ...
// In computer programming, the proxy pattern is a software design pattern. ...
Behavioral: Chain of responsibility • Command • Interpreter • Iterator • Mediator • Memento • Observer • State • Strategy • Template method • Visitor In Object Oriented Design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. ...
In object-oriented programming, the Command pattern is a design pattern in which objects are used to represent actions. ...
In computer programming, the interpreter pattern is a particular design pattern. ...
In object-oriented programming, an iterator is an object allowing one to sequence through all of the elements or parts contained in some other object, typically a container or list. ...
The mediator pattern is a software design pattern that provides a unified interface to a set of interfaces in a subsystem. ...
The memento pattern is a software design pattern that provides the ability to restore an object to its previous state (undo by rollback). ...
The observer pattern (sometimes known as publish/subscribe) is a design pattern used in computer programming to observe the state of an object in a program. ...
A behavioral software design pattern, state pattern is used in computer programming to represent the state of an object. ...
In computer programming, the strategy pattern is a particular software design pattern, whereby algorithms can be selected on-the-fly at runtime. ...
Template method: UML class diagram. ...
| |