Sunday, August 20, 2023

Visitor Pattern in Python...

 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 Pattern

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 medinine 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




No comments: