Factory Factory is great for:
class Dog:
"""A simple dog class"""
def __init__(self, name):
self._name = name
def speak(self):
return "Woof!"
class Cat:
"""A simple dog class"""
def __init__(self, name):
self._name = name
def speak(self):
return "Meow!"
def get_pet(pet="dog"):
"""The factory method"""
pets = dict(dog=Dog("Hope"), cat=Cat("Peace"))
return pets[pet]
d = get_pet("dog")
print(d.speak())
c = get_pet("cat")
print(c.speak())
The attribute name with a single underscore is called a weak private.In the factory function, the mission is really to create these objects and to return these objects to the user of the function.
Abstract Factory Abstract Factory is great for situations when the user expectation yields multiple related object until runtime.
class Dog:
"""One of the objects to be returned"""
def speak(self):
return "Woof!"
def __str__(self):
return "Dog"
class DogFactory:
"""Concrete Factory"""
def get_pet(self):
"""Returns a Dog object"""
return Dog()
def get_food(self):
"""Returns a Dog Food object"""
return "Dog Food!"
class PetStore:
""" PetStore houses our Abstract Factory """
def __init__(self, pet_factory=None):
""" pet_factory is our Abstract Factory """
self._pet_factory = pet_factory
def show_pet(self):
""" Utility method to display the details of the objects retured by the DogFactory """
pet = self._pet_factory.get_pet()
pet_food = self._pet_factory.get_food()
print("Our pet is '{}'!".format(pet))
print("Our pet says hello by '{}'".format(pet.speak()))
print("Its food is '{}'!".format(pet_food))
#Create a Concrete Factory
factory = DogFactory()
#Create a pet store housing our Abstract Factory
shop = PetStore(factory)
#Invoke the utility method to show the details of our pet
shop.show_pet()
Here we have one concrete factory(DogFactory), we can definitely create more concrete factories like CatFactory.
Singleton Singletons are used for:
A Singleton acts as an information cache share by multiple objects. Modules in Python act as Singletons.
class Borg:
"""Borg pattern making the class attributes global"""
_shared_data = {} # Attribute dictionary
def __init__(self):
self.__dict__ = self._shared_data # Make it an attribute dictionary
class Singleton(Borg): #Inherits from the Borg class
"""This class now shares all its attributes among its various instances"""
#This essenstially makes the singleton objects an object-oriented global variable
def __init__(self, **kwargs):
Borg.__init__(self)
self._shared_data.update(kwargs) # Update the attribute dictionary by inserting a new key-value pair
def __str__(self):
return str(self._shared_data) # Returns the attribute dictionary for printing
#Let's create a singleton object and add our first acronym
x = Singleton(HTTP="Hyper Text Transfer Protocol")
# Print the object
print(x)
#Let's create another singleton object and if it refers to the same attribute dictionary by adding another acronym.
y = Singleton(SNMP="Simple Network Management Protocol")
# Print the object
print(y)
Builder Builders are good at solving problems with building a complex object using an excessive number of constructors.
Solution: Director Abstract Builder: interfaces Concrete Builder: implements the interfaces Product: object being built
class Director():
"""Director"""
def __init__(self, builder):
self._builder = builder
def construct_car(self):
self._builder.create_new_car()
self._builder.add_model()
self._builder.add_tires()
self._builder.add_engine()
def get_car(self):
return self._builder.car
class Builder():
"""Abstract Builder"""
def __init__(self):
self.car = None
def create_new_car(self):
self.car = Car()
class SkyLarkBuilder(Builder):
"""Concrete Builder --> provides parts and tools to work on the parts """
def add_model(self):
self.car.model = "Skylark"
def add_tires(self):
self.car.tires = "Regular tires"
def add_engine(self):
self.car.engine = "Turbo engine"
class Car():
"""Product"""
def __init__(self):
self.model = None
self.tires = None
self.engine = None
def __str__(self):
return '{} | {} | {}'.format(self.model, self.tires, self.engine)
builder = SkyLarkBuilder()
director = Director(builder)
director.construct_car()
car = director.get_car()
print(car)
Prototype Prototypes work well in creating multiple identical items.
import copy
class Prototype:
def __init__(self):
self._objects = {}
def register_object(self, name, obj):
"""Register an object"""
self._objects[name] = obj
def unregister_object(self, name):
"""Unregister an object"""
del self._objects[name]
def clone(self, name, **attr):
"""Clone a registered object and update its attributes"""
obj = copy.deepcopy(self._objects.get(name))
obj.__dict__.update(attr)
return obj
class Car:
def __init__(self):
self.name = "Skylark"
self.color = "Red"
self.options = "Ex"
def __str__(self):
return '{} | {} | {}'.format(self.name, self.color, self.options)
c = Car()
prototype = Prototype()
prototype.register_object('skylark',c)
c1 = prototype.clone('skylark')
print(c1)
More Design Patterns in Python
Recommended Posts