• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Gof   Design Pattern
 

Gof Design Pattern

on

  • 3,298 views

 

Statistics

Views

Total Views
3,298
Views on SlideShare
3,296
Embed Views
2

Actions

Likes
2
Downloads
92
Comments
0

2 Embeds 2

http://www.slideshare.net 1
https://twitter.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Gof   Design Pattern Gof Design Pattern Presentation Transcript

    • A  design  pattern  names,  abstracts,  and  identifies  the  key  aspects  of  a  common  design  structure  that  make  it  useful  for  creating  a  reusable  object‐oriented  design.  The  design  pattern  identifies  the  What is a Design Pattern?  participating classes and instances, their roles and collaborations, and the distribution of responsibilities.  Christopher Alexander says, quot;Each pattern describes a problem which occurs over and over again in our  Each design pattern focuses on a particular object‐oriented design problem or issue. It describes when it  environment, and then describes the core of the solution to that problem, in such a way that you can  applies, whether it can be applied in view of other design constraints, and the consequences and trade‐ use this solution a million times over, without ever doing it the same way twicequot; [AIS+77, page x]. Even  offs of its use. Since we must eventually implement our designs, a design pattern also provides sample  though Alexander was talking about patterns in buildings and towns, what he says is true about object‐ C++ and (sometimes) Smalltalk code to illustrate an implementation.  oriented design patterns. Our solutions are expressed in terms of objects and interfaces instead of walls  Although  design  patterns  describe  object‐oriented  designs,  they  are  based  on  practical  solutions  that  and doors, but at the core of both kinds of patterns is a solution to a problem in a context.  have been implemented in mainstream object‐oriented programming languages like Smalltalk and C++  In general, a pattern has four essential elements:  rather  than  procedural  languages  (Pascal,  C,  Ada)  or  more  dynamic  object‐oriented  languages  (CLOS,  Dylan, Self). We chose Smalltalk and C++ for pragmatic reasons: Our day‐to‐day experience has been in  The pattern name is a handle we can use to describe a design problem, its solutions, and consequences  these languages, and they are increasingly popular.  in a word or two. Naming a pattern immediately increases our design vocabulary. It lets us design at a  higher level of abstraction. Having a vocabulary for patterns lets us talk about them with our colleagues,  The  choice  of  programming  language  is  important  because  it  influences  one's  point  of  view.  Our  in  our  documentation,  and  even  to  ourselves.  It  makes  it  easier  to  think  about  designs  and  to  patterns  assume  Smalltalk/C++‐level  language  features,  and  that  choice  determines  what  can  and  communicate  them  and  their  trade‐offs  to  others.  Finding  good  names  has  been  one  of  the  hardest  cannot  be  implemented  easily.  If  we  assumed  procedural  languages,  we  might  have  included  design  parts of developing our catalog.   patterns called quot;Inheritance,quot; quot;Encapsulation,quot; and quot;Polymorphism.quot; Similarly, some of our patterns are  supported  directly  by  the  less  common  object‐oriented  languages.  CLOS  has  multi‐methods,  for  The  problem  describes  when  to  apply  the  pattern.  It  explains  the  problem  and  its  context.  It  might  example,  which  lessen  the  need  for  a  pattern  such  as  Visitor  (page  331).  In  fact,  there  are  enough  describe specific design problems such as how to represent algorithms as objects. It might describe class  differences between Smalltalk and C++ to mean that some patterns can be expressed more easily in one  or object structures that are symptomatic of an inflexible design. Sometimes the problem will include a  language than the other. (See Iterator (257) for an example.)  list of conditions that must be met before it makes sense to apply the pattern.   The solution describes the elements that make up the design, their relationships, responsibilities,  and  Describing Design Patterns  collaborations. The solution doesn't describe a particular concrete design or implementation, because a  How do we describe design patterns? Graphical notations, while important and useful, aren't sufficient.  pattern is like a template that can be applied in many different situations. Instead, the pattern provides  They simply capture the end product of the design process as relationships between classes and objects.  an  abstract description  of  a design problem and how a general  arrangement of elements  (classes  and  To  reuse  the  design,  we  must  also  record  the  decisions,  alternatives,  and  trade‐offs  that  led  to  it.  objects in our case) solves it.   Concrete examples are important too, because they help you see the design in action.  The  consequences  are  the  results  and  trade‐offs  of  applying  the  pattern.  Though  consequences  are  We describe design patterns using a consistent format. Each pattern is divided into sections according to  often  unvoiced  when  we  describe  design  decisions,  they  are  critical  for  evaluating  design  alternatives  the  following  template.  The  template  lends  a  uniform  structure  to  the  information,  making  design  and  for  understanding  the  costs  and  benefits  of  applying  the  pattern.  The  consequences  for  software  patterns easier to learn, compare, and use.  often concern space and time trade‐offs. They may address language and implementation issues as well.  Since reuse is often a factor in object‐oriented design, the consequences of a pattern include its impact  Pattern Name and Classification   on  a  system's  flexibility,  extensibility,  or  portability.  Listing  these  consequences  explicitly  helps  you  The pattern's name conveys the essence of the pattern succinctly. A good name is vital, because it will  understand and evaluate them.   become part of your design vocabulary. The pattern's classification reflects the scheme we introduce in  Section 1.5.   Point  of  view  affects  one's  interpretation  of  what  is  and  isn't  a  pattern.  One  person's  pattern  can  be  another person's primitive building block. For this book we have concentrated on patterns at a certain  Intent   level of abstraction. Design patterns are not about designs such as linked lists and hash tables that can  A short statement that answers the following questions: What does the design pattern do? What is its  be  encoded  in  classes  and  reused  as  is.  Nor  are  they  complex,  domain‐specific  designs  for  an  entire  rationale and intent? What particular design issue or problem does it address?   application  or  subsystem.  The  design  patterns  in  this  book  are  descriptions  of  communicating  objects  and classes that are customized to solve a general design problem in a particular context.  Also Known As  
    • Other well‐known names for the pattern, if any.   notations as we introduce them in the upcoming discussions. Finally, Appendix C contains source code  for the foundation classes we use in code samples.  Motivation   A scenario that illustrates a design problem and how the class and object structures in the pattern solve  Creational patterns  the problem. The scenario will help you understand the more abstract description  of the  pattern that  follows.   Creational design patterns abstract the instantiation process. They help make a system independent of  how its objects are created, composed, and represented. A class creational pattern uses inheritance to  Applicability   vary  the  class  that's  instantiated,  whereas  an  object  creational  pattern  will  delegate  instantiation  to  What are the situations in which the design pattern can be applied? What are examples of poor designs  another object.   that the pattern can address? How can you recognize these situations?   Creational patterns become important as systems evolve to depend more on object composition than  Structure   class  inheritance.  As  that  happens,  emphasis  shifts  away  from  hard‐coding  a  fixed  set  of  behaviors  A graphical representation of the classes in the pattern using a notation based on the Object Modeling  toward defining a smaller set of fundamental behaviors that can be composed into any number of more  Technique (OMT) [RBP+91]. We also use interaction diagrams [JCJO92, Boo94] to illustrate sequences of  complex ones. Thus creating objects with particular behaviors requires more than simply instantiating a  requests and collaborations between objects. Appendix B describes these notations in detail.   class.   Participants   There  are  two  recurring  themes  in  these  patterns.  First,  they  all  encapsulate  knowledge  about  which  The classes and/or objects participating in the design pattern and their responsibilities.   concrete classes the system uses. Second, they hide how instances of these classes are created and put  together.  All  the  system  at  large  knows  about  the  objects  is  their  interfaces  as  defined  by  abstract  Collaborations   classes.  Consequently,  the  creational  patterns  give  you  a  lot  of  flexibility  in  what  gets  created,  who  How the participants collaborate to carry out their responsibilities.   creates it, how it gets created, and when. They let you configure a system with quot;productquot; objects that  Consequences   vary widely in structure and functionality. Configuration can be static (that is, specified at compile‐time)  How does the pattern support its objectives? What are the trade‐offs and results of using the pattern?  or dynamic (at run‐time).   What aspect of system structure does it let you vary independently?   Sometimes  creational  patterns  are  competitors.  For  example,  there  are  cases  when  either  Prototype  Implementation   (117) or Abstract Factory (87) could be used profitably. At other times they are complementary: Builder  What pitfalls, hints, or techniques should you be aware of when implementing the pattern? Are there  (97) can use one of the other patterns to implement which components get built. Prototype (117) can  language‐specific issues?   use Singleton (127) in its implementation.   Sample Code   Because the creational patterns are closely related, we'll study all five of them together to highlight their  Code fragments that illustrate how you might implement the pattern in C++ or Smalltalk.   similarities and differences. We'll also use a common example—building a maze for a computer game— to  illustrate  their  implementations.  The  maze  and  the  game  will vary  slightly  from  pattern  to  pattern.  Known Uses   Sometimes the game will be simply to find your way out of a maze; in that case the player will probably  Examples  of  the  pattern  found  in  real  systems.  We  include  at  least  two  examples  from  different  only  have  a  local  view  of  the  maze.  Sometimes  mazes  contain  problems  to  solve  and  dangers  to  domains.   overcome, and these games may provide a map of the part of the maze that has been explored.   Related Patterns   We'll ignore many details of what can be in a maze and whether a maze game has a single or multiple  What design patterns are closely related to this one? What are the important differences? With which  players. Instead, we'll just focus on how mazes get created. We define a maze as a set of rooms. A room  other patterns should this one be used?   knows its neighbors; possible neighbors are another room, a wall, or a door to another room.   The appendices provide background information that will help you understand the patterns and the  The  classes  Room,  Door,  and  Wall  define  the  components  of  the  maze  used  in  all  our  examples.  We  discussions surrounding them. Appendix A is a glossary of terminology we use. We've already  define  only  the  parts  of  these  classes  that  are  important  for  creating  a  maze.  We'll  ignore  players,  mentioned Appendix B, which presents the various notations. We'll also describe aspects of the  operations for displaying and wandering around in a maze, and other important functionality that isn't  relevant to building the maze.  
    • virtual void Enter(); The following diagram shows the relationships between these classes:   private: MapSite* _sides[4]; int _roomNumber; }; The following classes represent the wall or door that occurs on each side of a room.  class Wall : public MapSite { public: Wall(); virtual void Enter(); }; class Door : public MapSite { public: Door(Room* = 0, Room* = 0);   virtual void Enter(); Each room has four sides. We use an enumeration Direction in C++ implementations to specify the  Room* OtherSideFrom(Room*); north, south, east, and west sides of a room:  private: Room* _room1; enum Direction {North, South, East, West}; Room* _room2; The Smalltalk implementations use corresponding symbols to represent these directions.  bool _isOpen; }; The  class  MapSite  is  the  common  abstract  class  for  all  the  components  of  a  maze.  To  simplify  the  We need to know about more than just the parts of a maze. We'll also define a Maze class to represent  example, MapSite defines only  one operation, Enter.  Its meaning depends  on  what you're entering.  If  a collection of rooms. Maze can also find a particular room given a room number using its RoomNo  you enter a room, then your location changes. If you try to enter a door, then one of two things happen:  operation.  If the door is open, you go into the next room. If the door is closed, then you hurt your nose.  class Maze { class MapSite { public: public: Maze(); virtual void Enter() = 0; }; void AddRoom(Room*); Enter provides a simple basis for more sophisticated game operations. For example, if you are in a room  Room* RoomNo(int) const; private: and say quot;Go East,quot; the game can simply determine which MapSite is immediately to the east and then  // ... call Enter on it. The subclass‐specific Enter operation will figure out whether your location changed or  }; your nose got hurt. In a real game, Enter could take the player object that's moving about as an  RoomNo  could do  a  look‐up using  a  linear search,  a  hash table, or even a  simple array.  But we won't  argument.  worry about such details here. Instead, we'll focus on how to specify the components of a maze object.  Room is the concrete subclass of MapSite that defines the key relationships between components in the  Another  class  we  define  is  MazeGame,  which  creates  the  maze.  One  straightforward  way  to  create  a  maze. It maintains references to other MapSite objects and stores a room number. The number will  maze  is  with  a  series  of  operations  that  add  components  to  a  maze  and  then  interconnect  them.  For  identify rooms in the maze.  example,  the  following  member  function  will  create  a  maze  consisting  of  two  rooms  with  a  door  between them:  class Room : public MapSite { public: Maze* MazeGame::CreateMaze () { Room(int roomNo); Maze* aMaze = new Maze; Room* r1 = new Room(1); MapSite* GetSide(Direction) const; Room* r2 = new Room(2); void SetSide(Direction, MapSite*); Door* theDoor = new Door(r1, r2);
    • aMaze->AddRoom(r1); If  CreateMaze  is  parameterized  by  various  prototypical  room,  door,  and  wall  objects,  which  it  then  aMaze->AddRoom(r2); copies  and  adds  to  the  maze,  then  you  can  change  the  maze's  composition  by  replacing  these  prototypical objects with different ones. This is an example of the Prototype (117) pattern.   r1->SetSide(North, new Wall); r1->SetSide(East, theDoor); The remaining creational pattern, Singleton (127), can ensure there's only one maze per game and that  r1->SetSide(South, new Wall); r1->SetSide(West, new Wall); all game objects have ready access to it—without resorting to global variables or functions. Singleton  also makes it easy to extend or replace the maze without touching existing code.  r2->SetSide(North, new Wall); r2->SetSide(East, new Wall); r2->SetSide(South, new Wall); Structural patterns  r2->SetSide(West, theDoor); Structural patterns are concerned with how classes and objects are composed to form larger structures.  return aMaze; } Structural  class  patterns  use  inheritance  to  compose  interfaces  or  implementations.  As  a  simple  This function is pretty complicated, considering that all it does is create a maze with two rooms. There  example, consider how multiple inheritance mixes two or more classes into one. The result is a class that  are obvious ways to make it simpler. For example, the Room constructor could initialize the sides with  combines  the  properties  of  its  parent  classes.  This  pattern  is  particularly  useful  for  making  walls ahead of time. But that just moves the code somewhere else. The real problem with this member  independently developed class libraries work together. Another example is the class form of the Adapter  function  isn't  its  size  but  its  inflexibility.  It  hard‐codes  the  maze  layout.  Changing  the  layout  means  (139) pattern. In general, an adapter makes one interface (the adaptee's) conform to another, thereby  changing this member function, either by overriding it—which means reimplementing the whole thing— providing  a uniform abstraction of different interfaces. A class  adapter accomplishes this by inheriting  or by changing parts of it—which is error‐prone and doesn't promote reuse.  privately from an adaptee class. The adapter then expresses its interface in terms of the adaptee's.  The  creational  patterns  show  how  to  make  this  design  more  flexible,  not  necessarily  smaller.  In  Rather  than  composing  interfaces  or  implementations,  structural  object  patterns  describe  ways  to  particular, they will make it easy to change the classes that define the components of a maze.  compose  objects  to  realize  new  functionality.  The  added  flexibility  of  object  composition  comes  from  the ability to change the composition at run‐time, which is impossible with static class composition.  Suppose  you  wanted  to  reuse  an  existing  maze  layout  for  a  new  game  containing  (of  all  things)  enchanted mazes. The enchanted maze game has  new kinds of components, like  DoorNeedingSpell, a  Composite (163) is an example of a structural object pattern. It describes how to build a class hierarchy  door that can be locked and opened subsequently only with a spell; and EnchantedRoom, a room that  made  up  of  classes  for  two  kinds  of  objects:  primitive  and  composite.  The  composite  objects  let  you  can have unconventional items in it, like magic keys or spells. How can you change CreateMaze easily so  compose  primitive  and  other composite  objects  into  arbitrarily  complex structures.  In the Proxy (207)  that it creates mazes with these new classes of objects?  pattern, a proxy acts as a convenient surrogate or placeholder for another object. A proxy can be used in  many ways. It can act as a local representative for an object in a remote address space. It can represent  In  this  case,  the  biggest  barrier  to  change  lies  in  hard‐coding  the  classes  that  get  instantiated.  The  a large object that should be loaded on demand. It might protect access to a sensitive object. Proxies  creational patterns provide different ways to remove explicit references to concrete classes from code  provide a level of indirection to specific properties of objects. Hence they can restrict, enhance, or alter  that needs to instantiate them:  these properties.  If CreateMaze calls virtual functions instead of constructor calls to create the rooms, walls, and doors it  The Flyweight (195) pattern defines a structure for sharing objects. Objects are shared for at least two  requires, then you can change the classes that get instantiated by making a subclass of MazeGame and  reasons: efficiency and consistency. Flyweight focuses on sharing for space efficiency. Applications that  redefining those virtual functions. This approach is an example of the Factory Method (107) pattern.   use lots of objects must pay careful attention to the cost of each object. Substantial savings can be had  If CreateMaze is passed an object as a parameter to use to create rooms, walls, and doors, then you  by  sharing  objects  instead  of  replicating  them.  But  objects  can  be  shared  only  if  they  don't  define  can change the classes of rooms, walls, and doors by passing a different parameter. This is an example  context‐dependent state. Flyweight objects have no such state. Any additional information they need to  of the Abstract Factory (87) pattern.   perform their task is passed to them when needed. With no context‐dependent state, Flyweight objects  may be shared freely.  If CreateMaze is passed an object that can create a new maze in its entirety using operations for adding  rooms, doors, and walls to the maze it builds, then you can use inheritance to change parts of the maze  Whereas Flyweight shows how to make lots of little objects, Facade (185) shows how to make a single  or the way the maze is built. This is an example of the Builder (97) pattern.   object  represent  an  entire  subsystem.  A  facade  is  a  representative  for  a  set  of  objects.  The  facade  carries  out  its  responsibilities  by  forwarding  messages  to  the  objects  it  represents.  The  Bridge  (151) 
    • pattern  separates  an  object's  abstraction  from  its  implementation  so  that  you  can  vary  them  Other behavioral object patterns are concerned with encapsulating behavior in an object and delegating  independently.  requests to it. The Strategy (315) pattern encapsulates an algorithm in an object. Strategy makes it easy  to specify and change the algorithm an object uses. The Command (233) pattern encapsulates a request  Decorator (175) describes how to add responsibilities to objects dynamically. Decorator is a structural  in an object so that  it  can be passed as a parameter, stored on  a history list, or  manipulated in other  pattern that composes objects recursively to allow an open‐ended number of additional responsibilities.  ways.  The  State  (305)  pattern  encapsulates  the  states  of  an  object  so  that  the  object  can  change  its  For example, a Decorator object containing a user interface component can add a decoration like a  behavior  when  its  state  object  changes.  Visitor  (331)  encapsulates  behavior  that  would  otherwise  be  border or shadow to the component, or it can add functionality like scrolling and zooming. We can add  distributed  across  classes,  and  Iterator  (257)  abstracts  the  way  you  access  and  traverse  objects  in  an  two decorations simply by nesting one Decorator object within another, and so on for additional  aggregate.  decorations. To accomplish this, each Decorator object must conform to the interface of its component  and must forward messages to it. The Decorator can do its job (such as drawing a border around the  component) either before or after forwarding a message.   Behavioral patterns  Behavioral  patterns  are  concerned  with  algorithms  and  the  assignment  of  responsibilities  between  objects.  Behavioral  patterns  describe  not  just  patterns  of  objects  or  classes  but  also  the  patterns  of  communication  between  them.  These  patterns  characterize  complex  control  flow  that's  difficult  to  follow at run‐time. They shift your focus away from flow of control to let you concentrate just on the  way objects are interconnected.   Behavioral class patterns use inheritance to distribute behavior between classes. This chapter includes  two  such  patterns.  Template  Method  (325)  is  the  simpler  and  more  common  of  the  two.  A  template  method is an abstract definition of an algorithm. It defines the algorithm step by step. Each step invokes  either an abstract operation or a primitive operation. A subclass fleshes out the algorithm by defining  the  abstract  operations.  The  other  behavioral  class  pattern  is  Interpreter  (243),  which  represents  a  grammar  as  a  class  hierarchy  and  implements  an  interpreter  as  an  operation  on  instances  of  these  classes.   Behavioral object patterns use object composition rather than inheritance. Some describe how a group  of peer objects cooperate to perform a task that no single object can carry out by itself. An important  issue here is how peer objects know about each other. Peers could maintain explicit references to each  other,  but  that  would  increase  their  coupling.  In  the  extreme,  every  object  would  know  about  every  other.  The  Mediator  (273)  pattern  avoids  this  by  introducing  a  mediator  object  between  peers.  The  mediator provides the indirection needed for loose coupling.   Chain  of  Responsibility  (223)  provides  even  looser  coupling.  It  lets  you  send  requests  to  an  object  implicitly through a chain of candidate objects. Any candidate may fulfill the request depending on run‐ time  conditions.  The  number  of  candidates  is  open‐ended,  and  you  can  select  which  candidates  participate in the chain at run‐time.   The Observer (293) pattern defines and maintains a dependency between objects. The classic example  of Observer is in Smalltalk Model/View/Controller, where all views of the model are notified whenever  the model's state changes.  
    • visitor, it sends a request to the visitor that encodes the element's class. It also includes the element as  Visitor pattern  an argument. The visitor will then execute the operation for that element—the operation that used to  be in the class of the element.  Intent  For example, a compiler that didn't use visitors might type‐check a procedure by calling the TypeCheck  Represent an operation to be performed on the elements of an object structure. Visitor lets you define a  operation  on  its  abstract  syntax  tree.  Each  of  the  nodes  would  implement  TypeCheck  by  calling  new operation without changing the classes of the elements on which it operates.  TypeCheck  on  its  components  (see  the  preceding  class  diagram).  If  the  compiler  type‐checked  a  Motivation  procedure using visitors, then it would create a TypeCheckingVisitor object and call the Accept operation  on the abstract syntax tree with that object as an argument. Each of the nodes would implement Accept  Consider  a  compiler  that  represents  programs  as  abstract  syntax  trees.  It  will  need  to  perform  by calling back on the visitor: an assignment node calls VisitAssignment operation on the visitor, while a  operations  on  abstract  syntax  trees  for  quot;static  semanticquot;  analyses  like  checking  that  all  variables  are  variable  reference  calls  VisitVariableReference.  What  used  to  be  the  TypeCheck  operation  in  class  defined.  It  will  also  need  to  generate  code.  So  it  might  define  operations  for  type‐checking,  code  AssignmentNode is now the VisitAssignment operation on TypeCheckingVisitor.  optimization, flow analysis, checking for variables being assigned values before they're used, and so on.  Moreover,  we  could  use  the  abstract  syntax  trees  for  pretty‐printing,  program  restructuring,  code  To make visitors work for more than just type‐checking, we need an abstract parent class NodeVisitor  instrumentation, and computing various metrics of a program.  for all visitors of an abstract syntax tree. NodeVisitor must declare an operation for each node class. An  application that needs to compute program metrics will define new subclasses of NodeVisitor and will  Most  of  these  operations  will  need  to  treat  nodes  that  represent  assignment  statements  differently  no longer need to add application‐specific code to the node classes. The Visitor pattern encapsulates the  from  nodes  that  represent  variables  or  arithmetic  expressions.  Hence  there  will  be  one  class  for  operations for each compilation phase in a Visitor associated with that phase.  assignment  statements,  another  for  variable  accesses,  another  for  arithmetic  expressions,  and  so  on.  The set of node classes depends on the language being compiled, of course, but it doesn't change much  for a given language.      This  diagram  shows  part  of  the  Node  class  hierarchy.  The  problem  here  is  that  distributing  all  these  operations across the various node classes leads to a system that's hard to understand, maintain, and  change. It will be confusing to have type‐checking code mixed with pretty‐printing code or flow analysis  code. Moreover, adding a new operation usually requires recompiling all of these classes. It would be    better if each new operation could be added separately, and the node classes were independent of the  operations that apply to them.  With the Visitor pattern, you define two class hierarchies: one for the elements being operated on (the  Node  hierarchy)  and  one  for  the  visitors  that  define  operations  on  the  elements  (the  NodeVisitor  We can have both by packaging related operations from each class in a separate object, called a visitor,  hierarchy). You create a new operation by adding a new subclass to the visitor class hierarchy. As long as  and passing it to elements of the abstract syntax tree as it's traversed. When an element quot;acceptsquot; the 
    • the  grammar  that  the  compiler  accepts  doesn't  change  (that  is,  we  don't  have  to  add  new  Node  declares  a  Visit  operation  for  each  class  of  ConcreteElement  in  the  object  structure.  The  operation's  subclasses), we can add new functionality simply by defining new NodeVisitor subclasses.  name and signature identifies the class that sends  the Visit request to the visitor. That lets the visitor  determine  the  concrete  class  of  the  element  being  visited.  Then  the  visitor  can  access  the  element  Applicability  directly through its particular interface.   Use  the  Visitor  pattern  when  an  object  structure  contains  many  classes  of  objects  with  differing  ConcreteVisitor (TypeCheckingVisitor)   interfaces, and you want to perform operations on these objects that depend on their concrete classes.   implements each operation declared by Visitor. Each operation implements a fragment of the algorithm  many distinct and unrelated operations need to be performed on objects in an object structure, and you  defined for the corresponding class of object in the structure. ConcreteVisitor provides the context for  want  to  avoid  quot;pollutingquot;  their  classes  with  these  operations.  Visitor  lets  you  keep  related  operations  the algorithm and stores its local state. This state often accumulates results during the traversal of the  together by defining them in one class. When the object structure is shared by many applications, use  structure.   Visitor to put operations in just those applications that need them.   Element (Node)   the  classes  defining  the  object  structure  rarely  change,  but  you  often  want  to  define  new  operations  defines an Accept operation that takes a visitor as an argument.   over the structure. Changing the object structure classes requires redefining the interface to all visitors,  ConcreteElement (AssignmentNode,VariableRefNode)   which  is  potentially  costly.  If  the  object  structure  classes  change  often,  then  it's  probably  better  to  • implements an Accept operation that takes a visitor as an argument.   define the operations in those classes.   • ObjectStructure (Program)   Structure  • can enumerate its elements.   • may provide a high‐level interface to allow the visitor to visit its elements.   • may either be a composite (see Composite (163)) or a collection such as a list or a set.   Collaborations  A client that uses the Visitor pattern must create a ConcreteVisitor object and then traverse the object  structure, visiting each element with the visitor.   When  an  element  is  visited,  it  calls  the  Visitor  operation  that  corresponds  to  its  class.  The  element  supplies itself as an argument to this operation to let the visitor access its state, if necessary.   The  following  interaction  diagram  illustrates  the  collaborations  between  an  object  structure,  a  visitor,  and two elements:    Participants    Visitor (NodeVisitor)  
    • Consequences  MyType and YourType do not have to be related through inheritance at all.  Some of the benefits and liabilities of the Visitor pattern are as follows:  Accumulating  state.  Visitors  can  accumulate  state  as  they  visit  each  element  in  the  object  structure.  Without  a  visitor,  this  state  would  be  passed  as  extra  arguments  to  the  operations  that  perform  the  Visitor makes adding new operations easy. Visitors make it easy to add operations that depend on the  traversal, or they might appear as global variables.   components  of  complex  objects.  You  can  define  a  new  operation  over  an  object  structure  simply  by  adding a new visitor. In contrast, if you spread functionality over many classes, then you must change  Breaking  encapsulation.  Visitor's  approach  assumes  that  the  ConcreteElement  interface  is  powerful  each class to define a new operation.   enough to let visitors do their job. As a result, the pattern often forces you to provide public operations  that access an element's internal state, which may compromise its encapsulation.   A visitor gathers related operations and separates unrelated ones. Related behavior isn't spread over the  classes defining the object structure; it's localized in a visitor. Unrelated sets of behavior are partitioned  Implementation  in their own visitor subclasses. That simplifies both the classes defining the elements and the algorithms  Each  object  structure  will  have  an  associated  Visitor  class.  This  abstract  visitor  class  declares  a  defined in the visitors. Any algorithm‐specific data structures can be hidden in the visitor.   VisitConcreteElement  operation  for  each  class  of  ConcreteElement  defining  the  object  structure.  Each  Adding new ConcreteElement classes is hard. The Visitor pattern makes it hard to add new subclasses of  Visit  operation  on  the  Visitor  declares  its  argument  to  be  a  particular  ConcreteElement,  allowing  the  Element.  Each  new  ConcreteElement  gives  rise  to  a  new  abstract  operation  on  Visitor  and  a  Visitor  to  access  the  interface  of  the  ConcreteElement  directly.  ConcreteVisitor  classes  override  each  corresponding implementation in every ConcreteVisitor class. Sometimes a default implementation can  Visit operation to implement visitor‐specific behavior for the corresponding ConcreteElement class.  be  provided  in  Visitor  that  can be  inherited  by  most  of  the  ConcreteVisitors,  but  this  is  the  exception  The Visitor class would be declared like this in C++:  rather than the rule.   class Visitor { So the key consideration in applying the Visitor pattern is whether you are mostly likely to change the  public: algorithm  applied  over  an  object  structure  or  the  classes  of  objects  that  make  up  the  structure.  The  virtual void VisitElementA(ElementA*); virtual void VisitElementB(ElementB*); Visitor  class  hierarchy  can  be  difficult  to  maintain  when  new  ConcreteElement  classes  are  added  frequently. In such cases, it's probably easier just to define operations on the classes that make up the  // and so on for other concrete elements structure. If the Element class hierarchy is stable, but you are continually adding operations or changing  protected: Visitor(); algorithms, then the Visitor pattern will help you manage the changes.  }; Each class of ConcreteElement implements an Accept operation that calls the matching Visit... operation  Visiting across class hierarchies. An iterator (see Iterator (257)) can visit the objects in a structure as it  on the visitor for that ConcreteElement. Thus the operation that ends up getting called depends on both  traverses  them  by  calling  their  operations.  But  an  iterator  can't  work  across  object  structures  with  the class of the element and the class of the visitor.10  different  types  of  elements.  For  example,  the  Iterator  interface  defined  on  page  263  can  access  only  objects of type Item:   The concrete elements are declared as  1. template <class Item> class Element { 2. class Iterator { public: 3. // ... virtual ~Element(); 4. Item CurrentItem() const; virtual void Accept(Visitor&) = 0; 5. }; protected: This implies that all elements the iterator can visit have a common parent class Item.  Element(); }; Visitor does not have this restriction. It can visit objects that don't have a common parent class. You can  class ElementA : public Element { add any type of object to a Visitor interface. For example, in  public: ElementA(); class Visitor { virtual void Accept(Visitor& v) { v.VisitElementA(this); } public: }; // ... void VisitMyType(MyType*); class ElementB : public Element { void VisitYourType(YourType*); public: }; ElementB();
    • virtual void Accept(Visitor& v) { v.VisitElementB(this); } Often the object structure is responsible for iteration. A collection will simply iterate over its elements,  }; calling the Accept operation on each. A composite will commonly traverse itself by having each Accept  A CompositeElement class might implement Accept like this:  operation traverse the element's children and call Accept on each of them recursively.  class CompositeElement : public Element { Another solution is to use an iterator to visit the elements. In C++, you could use either an internal or  public: virtual void Accept(Visitor&); external iterator, depending on what is available and what is most efficient. In Smalltalk, you usually use  private: an  internal  iterator  using  do:  and  a  block.  Since  internal  iterators  are  implemented  by  the  object  List<Element*>* _children; structure, using an internal iterator is a lot like making the object structure responsible for iteration. The  }; main difference is that an internal iterator will not cause double‐dispatching—it will call an operation on  void CompositeElement::Accept (Visitor& v) { the visitor with an element as an argument as opposed to calling an operation on the element with the  ListIterator<Element*> i(_children); visitor as an argument. But it's easy to use the Visitor pattern with an internal iterator if the operation  for (i.First(); !i.IsDone(); i.Next()) { on the visitor simply calls the operation on the element without recursing.  i.CurrentItem()->Accept(v); } You could even put the traversal algorithm in the visitor, although you'll end up duplicating the traversal  v.VisitCompositeElement(this); code in each ConcreteVisitor for each aggregate ConcreteElement. The main reason to put the traversal  } Here are two other implementation issues that arise when you apply the Visitor pattern:  strategy in the visitor is to implement a particularly complex traversal, one that depends on the results  of the operations on the object structure. We'll give an example of such a case in the Sample Code.  Double  dispatch.  Effectively,  the  Visitor  pattern  lets  you  add  operations  to  classes  without  changing  them. Visitor achieves this by using a technique called double‐dispatch. It's a well‐known technique. In  Sample Code  fact,  some  programming  languages  support  it  directly  (CLOS,  for  example).  Languages  like  C++  and  Because visitors are usually associated with composites, we'll use the Equipment classes defined in the  Smalltalk support single‐dispatch.   Sample Code of Composite (163) to illustrate the Visitor pattern. We will use Visitor to define operations  for  computing  the  inventory  of  materials and  the  total  cost  for  a piece  of  equipment.  The Equipment  In single‐dispatch languages, two criteria determine which operation will fulfill a request: the name of  classes  are  so  simple  that  using  Visitor  isn't  really  necessary,  but  they  make  it  easy  to  see  what's  the request and the type of receiver. For example, the operation that a GenerateCode request will call  involved in implementing the pattern.  depends  on  the  type  of  node  object  you  ask.  In  C++,  calling  GenerateCode  on  an  instance  of  VariableRefNode  will  call  VariableRefNode::GenerateCode  (which  generates  code  for  a  variable  Here again is the Equipment class from Composite (163). We've augmented it with an Accept operation  reference).  Calling  GenerateCode  on  an  AssignmentNode  will  call  AssignmentNode::GenerateCode  to let it work with a visitor.  (which  will  generate  code  for  an  assignment).  The operation  that  gets  executed  depends  both  on  the  class Equipment { kind of request and the type of the receiver.  public: virtual ~Equipment(); quot;Double‐dispatchquot; simply means the operation that gets executed depends on the kind of request and  the types  of two receivers. Accept is a double‐dispatch operation. Its meaning depends on two  types:  const char* Name() { return _name; } the  Visitor's  and  the  Element's.  Double‐dispatching  lets  visitors  request  different  operations  on  each  virtual Watt Power(); class of element.11  virtual Currency NetPrice(); virtual Currency DiscountPrice(); This  is  the  key  to  the  Visitor  pattern:  The  operation  that  gets  executed  depends  on  both  the  type  of  virtual void Accept(EquipmentVisitor&); Visitor  and  the  type  of  Element  it  visits.  Instead  of  binding  operations  statically  into  the  Element  protected: interface, you can consolidate the operations in a Visitor and use Accept to do the binding at run‐time.  Equipment(const char*); Extending  the  Element  interface  amounts  to  defining  one  new  Visitor  subclass  rather  than  many  new  private: const char* _name; Element subclasses.  }; The Equipment operations return the attributes of a piece of equipment, such as its power consumption  Who  is  responsible  for  traversing  the  object  structure?  A  visitor  must  visit  each  element  of  the  object  and  cost.  Subclasses  redefine  these  operations  appropriately  for  specific  types  of  equipment  (e.g.,  a  structure. The question is, how does it get there? We can put responsibility for traversal in any of three  chassis, drives, and planar boards).  places: in the object structure, in the visitor, or in a separate iterator object (see Iterator (257)).  
    • Currency _total; The abstract class for all visitors of equipment has a virtual function for each subclass of equipment, as  }; shown next. All of the virtual functions do nothing by default.  void PricingVisitor::VisitFloppyDisk (FloppyDisk* e) { class EquipmentVisitor { _total += e->NetPrice(); public: } virtual ~EquipmentVisitor(); void PricingVisitor::VisitChassis (Chassis* e) { virtual void VisitFloppyDisk(FloppyDisk*); _total += e->DiscountPrice(); virtual void VisitCard(Card*); } virtual void VisitChassis(Chassis*); PricingVisitor  will  compute  the  total  cost  of  all  nodes  in  the  equipment  structure.  Note  that  virtual void VisitBus(Bus*); PricingVisitor  chooses  the  appropriate  pricing  policy  for  a  class  of  equipment  by  dispatching  to  the  // and so on for other concrete subclasses of Equipment corresponding  member  function.  What's  more,  we  can  change  the  pricing  policy  of  an  equipment  protected: structure just by changing the PricingVisitor class.  EquipmentVisitor(); }; We can define a visitor for computing inventory like this:   Equipment subclasses define Accept in basically the same way: It calls the EquipmentVisitor operation  that corresponds to the class that received the Accept request, like this:  class InventoryVisitor : public EquipmentVisitor { public: void FloppyDisk::Accept (EquipmentVisitor& visitor) { InventoryVisitor(); visitor.VisitFloppyDisk(this); } Inventory& GetInventory(); Equipment that contains other equipment (in particular, subclasses of CompositeEquipment in the  Composite pattern) implements Accept by iterating over its children and calling Accept on each of them.  virtual void VisitFloppyDisk(FloppyDisk*); virtual void VisitCard(Card*); Then it calls the Visit operation as usual. For example, Chassis::Accept could traverse all the parts in the  virtual void VisitChassis(Chassis*); chassis as follows:  virtual void VisitBus(Bus*); // ... void Chassis::Accept (EquipmentVisitor& visitor) { for ( private: ListIterator i(_parts); Inventory _inventory; !i.IsDone(); }; i.Next() The InventoryVisitor accumulates the totals for each type of equipment in the object structure.  ){ InventoryVisitor uses an Inventory class that defines an interface for adding equipment (which we won't  i.CurrentItem()->Accept(visitor); bother defining here).  } visitor.VisitChassis(this); } void InventoryVisitor::VisitFloppyDisk (FloppyDisk* e) { _inventory.Accumulate(e); Subclasses of EquipmentVisitor define particular algorithms over the equipment structure. The  } PricingVisitor computes the cost of the equipment structure. It computes the net price of all simple  equipment (e.g., floppies) and the discount price of all composite equipment (e.g., chassis and buses).  void InventoryVisitor::VisitChassis (Chassis* e) { _inventory.Accumulate(e); class PricingVisitor : public EquipmentVisitor { } public: Here's how we can use an InventoryVisitor on an equipment structure:  PricingVisitor(); Equipment* component; Currency& GetTotalPrice(); InventoryVisitor visitor; virtual void VisitFloppyDisk(FloppyDisk*); component->Accept(visitor); virtual void VisitCard(Card*); cout << quot;Inventory quot; virtual void VisitChassis(Chassis*); << component->Name() virtual void VisitBus(Bus*); << visitor.GetInventory(); // ... private:
    • [:stream | tStream := stream copy. Now we'll show how to implement the Smalltalk example from the Interpreter pattern (see page 248)  (tStream nextAvailable: with the Visitor pattern. Like the previous example, this one is so small that Visitor probably won't buy  literalExp components size us much, but it provides a good illustration of how to use the pattern. Further, it illustrates a situation in  ) = literalExp components ifTrue: [finalState add: tStream] which iteration is the visitor's responsibility.  ]. ^ finalState The  object  structure  (regular  expressions)  is  made  of  four  classes,  and  all  of  them  have  an  accept:  Known Uses  method that takes the visitor as an argument. In class SequenceExpression, the accept: method is  The  Smalltalk‐80  compiler  has  a  Visitor  class  called  ProgramNodeEnumerator.  It's  used  primarily  for  accept: aVisitor algorithms  that  analyze  source  code.  It  isn't  used  for  code  generation  or  pretty‐printing,  although  it  ^ aVisitor visitSequence: self In  class  RepeatExpression,  the  accept:  method  sends  the  visitRepeat:  message.  In  class  could be.  AlternationExpression,  it  sends  the  visitAlternation:  message.  In  class  LiteralExpression,  it  sends  the  IRIS Inventor  [Str93]  is  a  toolkit  for  developing  3‐D  graphics applications.  Inventor  represents  a  three‐ visitLiteral: message.  dimensional scene as a hierarchy of nodes, each representing either a geometric object or an attribute  The  four  classes  also  must  have  accessing  functions  that  the  visitor  can  use.  For  SequenceExpression  of one. Operations like rendering a scene or mapping an input event require traversing this hierarchy in  these  are  expression1  and  expression2;  for  AlternationExpression  these  are  alternative1  and  different  ways.  Inventor  does  this  using  visitors  called  quot;actions.quot;  There  are  different  visitors  for  alternative2; for RepeatExpression it is repetition; and for LiteralExpression these are components.  rendering, event handling, searching, filing, and determining bounding boxes.  The  ConcreteVisitor  class  is  REMatchingVisitor.  It  is  responsible  for  the  traversal  because  its  traversal  To make adding new nodes easier, Inventor implements a double‐dispatch scheme for C++. The scheme  algorithm  is  irregular.  The  biggest  irregularity  is  that  a  RepeatExpression  will  repeatedly  traverse  its  relies on run‐time type information  and a  two‐dimensional  table in which rows  represent visitors  and  component. The class REMatchingVisitor has an instance variable inputState. Its methods are essentially  columns represent node classes. The cells store a pointer to the function bound to the visitor and node  the same as the match: methods of the expression classes in the Interpreter pattern except they replace  class.  the argument named inputState with the expression node being matched. However, they still return the  Mark  Linton  coined  the  term  quot;Visitorquot;  in  the  X  Consortium's  Fresco  Application  Toolkit  specification  set of streams that the expression would match to identify the current state.  [LP93].  visitSequence: sequenceExp Related Patterns  inputState := sequenceExp expression1 accept: self. ^ sequenceExp expression2 accept: self. Composite (163): Visitors can be used to apply an operation over an object structure defined by the  visitRepeat: repeatExp Composite pattern.  | finalState | finalState := inputState copy. Interpreter (243): Visitor may be applied to do the interpretation.  [inputState isEmpty] whileFalse: [inputState := repeatExp repetition accept: self. finalState addAll: inputState]. ^ finalState visitAlternation: alternateExp | finalState originalState | originalState := inputState. finalState := alternateExp alternative1 accept: self. inputState := originalState. finalState addAll: (alternateExp alternative2 accept: self). ^ finalState visitLiteral: literalExp | finalState tStream | finalState := Set new. inputState do: