Visitor

Buffer this pageShare on FacebookPrint this pageTweet about this on TwitterShare on Google+Share on LinkedInShare on StumbleUpon
Reading Time: 1 minutes

Visitor Design Pattern in Python

Visitor Design Pattern in Python

Design Patterns Home
 

What is it?

The Visitor Design Pattern is adopted to add new features to an existing class hierarchy dynamically without changing it.

It is classified under Behavioural Design Patterns as it provides a good method to handle communication between objects.


Why the need for it: Problem Statement

The need for the Visitor Design Pattern arises when there is a requirement to add new operations to existing classes dynamically with minimal/no code changes.


Pseduo Code

# The Crops hierarchy cannot be changed to add new functionality dynamically.
# Abstract Crop class for Concrete Crop classes: methods defined in this class will be inherited by all Concrete Crop classes.
class Crop:
    def accept(visitor):
        calls visitor's visit()
    def sow(visitor):
        method to be invoked by one of the visitors
    def irrigate(visitor):
        method to be invoked by one of the visitors
    def harvest(visitor):
        method to be invoked by one of the visitors
    def __str__(self):
        returns name of crop class when printed

# Concrete Crops: Classes being visited.
class Wheat(Crop): pass
class Corn(Crop): pass
class Tomato(Crop): pass




# Abstract Visitor class for Concrete Visitor classes: method defined in this class will be inherited by all Concrete Visitor classes.
class Visitor:
    def __str__(self):
        returns name of visitor class when printed

# Concrete Visitors: Classes visiting Concrete Crop objects. These classes have a visit() method which is called by the accept() method of the Concrete Crop classes.
class GardenerOne(Visitor):
    def visit(crop):
        calls a method of the crop class, say sow()

class GardenerTwo(Visitor):
    def visit(crop):
        calls a method of the crop class, say irrigate()

class GardenerThree(Visitor):
    def visit(crop):
        calls a method of the crop class, say harvest()


### USING THE ABOVE SETUP ###
# Create Plants
# Create Visitors
# Call accept method of plant objects, one by one, passing a visitor as argument

How to implement it

# The Crops hierarchy cannot be changed to add new functionality dynamically.
# Abstract Crop class for Concrete Crop classes: methods defined in this class will be inherited by all Concrete Crop classes.
class Crop:
    def accept(self, visitor):
        visitor.visit(self)
    def sow(self, visitor):
        print(self, "Sown by", visitor)
    def irrigate(self, visitor):
        print(self, "Irrigated by", visitor)
    def harvest(self, visitor):
        print(self, "Harvested by", visitor)
    def __str__(self):
        return self.__class__.__name__

# Concrete Crops: Classes being visited.
class Wheat(Crop): pass
class Corn(Crop): pass
class Tomato(Crop): pass




# Abstract Visitor class for Concrete Visitor classes: method defined in this class will be inherited by all Concrete Visitor classes.
class Visitor:
    def __str__(self):
        return self.__class__.__name__

# Concrete Visitors: Classes visiting Concrete Crop objects. These classes have a visit() method which is called by the accept() method of the Concrete Crop classes.
class GardenerOne(Visitor):
    def visit(self, crop):
        crop.sow(self)

class GardenerTwo(Visitor):
    def visit(self, crop):
        crop.irrigate(self)

class GardenerThree(Visitor):
    def visit(self, crop):
        crop.harvest(self)


### USING THE ABOVE SETUP ###
# Creating Plants
wheatPatch = Wheat()
cornPatch = Corn()
tomatoPatch = Tomato()

# Creating Visitors
gardenerOne = GardenerOne()
gardenerTwo = GardenerTwo()
gardenerThree = GardenerThree()

# Visitors visiting Plants
wheatPatch.accept(gardenerOne)
wheatPatch.accept(gardenerTwo)
wheatPatch.accept(gardenerThree)

cornPatch.accept(gardenerOne)
cornPatch.accept(gardenerTwo)
cornPatch.accept(gardenerThree)

tomatoPatch.accept(gardenerOne)
tomatoPatch.accept(gardenerTwo)
tomatoPatch.accept(gardenerThree)


### OUTPUT ###
Wheat Sown by GardenerOne
Wheat Irrigated by GardenerTwo
Wheat Harvested by GardenerThree
Corn Sown by GardenerOne
Corn Irrigated by GardenerTwo
Corn Harvested by GardenerThree
Tomato Sown by GardenerOne
Tomato Irrigated by GardenerTwo
Tomato Harvested by GardenerThree

 

 

 

 


See also:

Buffer this pageShare on FacebookPrint this pageTweet about this on TwitterShare on Google+Share on LinkedInShare on StumbleUpon

Leave a Reply