Skip to main content

Command Palette

Search for a command to run...

Visitor Pattern in Python...

Updated
3 min read
S
In search of WhoAmI...

Visitor design pattern allows the addition of completely different functionalities to an existing class without much alteration in the original class.

Let me explain it with an example.

Suppose there are two items a shop sells - Book and Medicine

Now say, normally these two Item classes would look like two - what we call in Java as POJO classes where the most important attribute will be the price.

So far so good.

Now suppose the government is running

- one literacy mission

and

- one Health mission

Under these missions, few books are given huge discounts, and few medicines are sold at discounted prices.

Without the Visitor pattern, the algorithm of the discounts would have been put inside the POJO classes which might create maintenance problems in the future when the algorithm for discount changes.

With the visitor pattern, we encapsulate all these discount algorithms inside a special method called visit which comes from a Visitor interface.

So if it is a LiteracyMissionVisitor, the special algorithm offers a discount on special books whereas if it is a HealthMissionVisitor, the discount goes to specific medicines – all we have to do is to call accept on these special Book and Medicine objects passing the proper Visitor object,

That's it...

The UML class diagram looks as follows:

And here goes the source code of this Visitor PatternHere's the formatted version of your Python code using proper indentation and spacing:

from abc import ABC, abstractmethod

class Visitor(ABC):
    @abstractmethod
    def visit(self, book):
        pass

    @abstractmethod
    def visit(self, medicine):
        pass

class Visitable(ABC):
    @abstractmethod
    def accept(self, visitor):
        pass

class Book(Visitable):
    def __init__(self, price):
        self.price = price

    def accept(self, visitor):
        return visitor.visit(self)

    def getPrice(self):
        return self.price

class Medicine(Visitable):
    def __init__(self, price):
        self.price = price

    def accept(self, visitor):
        return visitor.visit(self)

    def getPrice(self):
        return self.price

class LiteracyMissionVisitor(Visitor):
    def __init__(self, percentagediscountOnBook):
        self.discount = percentagediscountOnBook

    def visit(self, book):
        book.price = book.price - (book.price * self.discount) / 100
        return book.price

class HealthMissionVisitor(Visitor):
    def __init__(self, percentagediscountOnMedicine):
        self.discount = percentagediscountOnMedicine

    def visit(self, medicine):
        medicine.price = medicine.price - (medicine.price * self.discount) / 100
        return medicine.price

# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    literacyMissionVisitor = LiteracyMissionVisitor(50)
    chandaMama = Book(100)
    print("Original price of the book is ", chandaMama.getPrice())
    print("Due to literacy mission, there is huge discount on the book. After discount, the price is ", chandaMama.accept(literacyMissionVisitor))

    healthDriveVisitor = HealthMissionVisitor(70)
    vitaminDCapsule = Medicine(200)
    print("Original price of the medicine is ", vitaminDCapsule.getPrice())
    print("Due to health mission the reduced price of the medicine is ", vitaminDCapsule.accept(healthDriveVisitor))

If we run this program, the output will be as follows:

Original price of the book is 100

Due to literacy mission, there is huge discount on the book. After discount, the price is 50.0

Original price of the medinine is 200

Due to health mission the reduced price of the medicine is 60.0

Enjoy…

More from this blog

Som's Tech World...

149 posts

I am in search of WhoAmI. This is my own world of technologies and software. I believe in the following simple fact of life... To win is no more than this... To rise each time you fall...

Visitor Pattern in Python...