Visitor Pattern

When you have File class with all print(), email() with inherited classes to WordFile, PictireFile, PreadSheet, …. Your new requirement are adding compress method on each classes. This is simple hierarchy structure. To add compress function you need to visit every class inherited from File. For visitor class you can create CompressVisitor class with visiteWord, visitPictire, visitSpeadSheet.

As per the pattern, element object has the visitor object so that visitor object handles the operation on the element object.

import abc
class File(abc.ABC):
def __init__(self, txt):
self.txt = txt
@abc.abstractmethod
def visit(self):
pass
class WordFile(File):
def __init__(self, txt):
super().__init__(txt)
def visit(self, fileVisitor):
fileVisitor.visitWord(self)
def __str__(self):
return self.txt

class PictureFile(File):
def __init__(self, txt):
super().__init__(txt)
def visit(self, fileVisitor):
fileVisitor.visitPicture(self)
def __str__(self):
return self.txt

class FileVisitor(abc.ABC):
@abc.abstractmethod
def visitWord(self):
pass
@abc.abstractmethod
def visitPicture(self):
pass

class PrintVisitor(FileVisitor):
def visitWord(self, wordFile):
print("Print Visitor ", wordFile)

def visitPicture(self, pictureFile):
print("Print Visitor ", pictureFile)

class EmailVisitor(FileVisitor):
def visitWord(self, wordFile):
print("Email Visitor ", wordFile)

def visitPicture(self, pictureFile):
print("Email Visitor ", pictureFile)

class CompressVisitor(FileVisitor):
def visitWord(self, wordFile):
print("Compress Visitor ", wordFile)

def visitPicture(self, pictureFile):
print("Compress Visitor ", pictureFile)

l = list()
l.append(WordFile("wordFile"))
l.append(PictureFile("pictireFile"))

printv = PrintVisitor()
for f in l:
f.visit(printv)

compressv = CompressVisitor()
for f in l:
f.visit(compressv)

emailv = EmailVisitor()
for f in l:
f.visit(emailv)
import abc
class Animal(abc.ABC):
@abc.abstractmethod
def visit(self, obj):
pass

class Dog(Animal):
def __init__(self, name):
self.name = name
def visit(self, visitor):
visitor.visit(self)
class Cat(Animal):
def __init__(self, name):
self.name = name
def visit(self, visitor):
visitor.visit(self)
class Horse(Animal):
def __init__(self, name):
self.name = name
def visit(self, visitor):
visitor.visit(self)
class Cow(Animal):
def __init__(self, name):
self.name = name
def visit(self, visitor):
visitor.visit(self)
class Visitor:
def visit(self, obj):
if isinstance(obj, Dog):
print(f"Take a walk for 30 min with {obj.name}")
elif isinstance(obj, Cat):
print(f"Let {obj.name} alone")
elif isinstance(obj, Horse):
print(f"Ride {obj.name} for horse riding")
elif isinstance(obj, Cow):
print(f"Extract milk for {obj.name}")

farm = [Dog("Willie"), Cat("Billie"), Horse("Charle"), Cow("Bullie"), Dog("Zollie")]
visitor = Visitor()
for anmimal in farm:
anmimal.visit(visitor)

Facade Pattern

Facade pattern hides the complexities of the system and provides an interface to the client using which the client can access the system. This type of design pattern comes under structural pattern as this pattern adds an interface to existing system to hide its complexities.

class Compiler:
def __init__(self, path):
self.path = path
def compile(self):
tokenizer = Tokenizer(self.path).tokenize()
parser = Parser(tokenizer).parse()
builder = IRBuilder(parser).build()
optimizer = Optimizer(builder).optimize()
codegenerator = CodeGenerator(optimizer).generate()
linker = Linker(codegenerator).link()
return linker
class Tokenizer:
def __init__(self, path):
self.path = path
def tokenize(self):
print(f"tokenizing {self.path}")
return self
def __str__(self):
return "Tokenizer"
class Parser:
def __init__(self, tokenizer):
self.tokenizer = tokenizer
def parse(self):
print("parsinging", end=" ")
print(self.tokenizer)
return self
def __str__(self):
return "Parser"
class IRBuilder:
def __init__(self, parser):
self.parser = parser
def build(self):
print("IRbuilding", end=" ")
print(self.parser)
return self
def __str__(self):
return "IRBuilder"
class Optimizer:
def __init__(self, builder):
self.builder = builder
def optimize(self):
print("optimizing", end=" ")
print(self.builder)
return self
def __str__(self):
return "Optimizer"
class CodeGenerator:
def __init__(self, optimizer):
self.optimizer = optimizer
def generate(self):
print("generating code", end=" ")
print(self.optimizer)
return self
def __str__(self):
return "CodeGenerator"
class Linker:
def __init__(self, generator):
self.codegenerator = generator
def link(self):
print("linking",end=" ")
print(self.codegenerator)
return self
def __str__(self):
return "Linker"
compiler = Compiler("sample.py")
compiler.compile()
class Washing:
'''Subsystem # 1'''
def wash(self):
print("Washing...")


class Rinsing:
'''Subsystem # 2'''
def rinse(self):
print("Rinsing...")


class Spinning:
'''Subsystem # 3'''
def spin(self):
print("Spinning...")

class WashingMachine:
'''Facade'''

def __init__(self):
self.washing = Washing()
self.rinsing = Rinsing()
self.spinning = Spinning()

def startWashing(self):
self.washing.wash()
self.rinsing.rinse()
self.spinning.spin()

Decorator Pattern

import abc
class Shape(abc.ABC):
@abc.abstractmethod
def draw(self):
pass

class Triangle(Shape):
def draw(self):
print("Triangle")

class Circle(Shape):
def draw(self):
print("Circle")

# Decorator was not needed to be inherited from Shape in Python.But you can enforce the draw function
# In Java, inheritance forces to implement parent methods to child Decorators.
class Decorator(Shape):
def __init__(self, shape):
self.shape = shape

class ColorDecorator(Decorator):
def __init__(self, shape, color):
super().__init__(shape)
self.color = color

def draw(self):
print(self.color)
self.shape.draw()
print(self.color)

class PatternDecorator(Decorator):
def __init__(self, shape, pattern):
super().__init__(shape)
self.pattern = pattern

def draw(self):
print(self.pattern)
self.shape.draw()
print(self.pattern)

s = Circle()
s.draw()
cd = ColorDecorator(s, "red")
cd.draw()
pd = PatternDecorator(Triangle(), "Polca dot")
pd.draw()
redPolcaDorCircle = PatternDecorator(cd, "Polca dot")
redPolcaDorCircle.draw()