arrow_back

Learn these 5 important OOP patterns

Introduction

Today we'll be going going through 5 important OOP patterns, which includes Single Ton, Factory, Builder, Adapter and Observer. OOP becomes hard but it isn't in reality, its just the mind which makes you think that these confusing words are probably hard, lets take Single Ton for example, its one of the simplest design pattern. Load up your favourite code editor we'll gonna write some code.

Single Ton

Single Ton pattern restricts the instantiation of the class to one, means you cannot create more than one instance of that particular class, this is useful when you have database and you want to connect to it and then passing that instance to different methods, classes or functions. Angular for example uses "Services" as a single ton, we're not learning angular here but services connect to out topic. Don't they? So the services are basically object/classes to manage our data, they methods which act upons the data and etc. Angular doesn't want us to create pattern from scratch so they have a typescript decorator for that. Well anyways Single Ton is useful when you only want to create one instance of the class and do something with it.

Let's create a small Single Ton example with python

class User:
    instance = None
    def __new__(cls, name, age, email):
        if cls.instance == None:
            instance = object.__new__(cls)
            instance.name = name
            instance.age = age
            instance.email = email
        return instance

Here we are creating a class called User then we create an attribute called instance which has value of None, then we modify the __new__ method and we check if the instance is empty if yes we create an instance, if no then we just return the existing instance.

Factory

Factory design pattern is used to create objects, it maybe useful when you're creating a game and you have tons of characters with different abilities, you can use the factory pattern there, and it will create the instance and return it. It is used alot in Java.

class Shape:
    def draw(self):
        pass

class Rectangle(Shape):
    def draw(self):
        print("Draw Rectangle")


class Square(Shape):
    def draw(self):
        print("Draw Sqaure")

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

class ShapeFactory:
    @staticmethod
    def get_shape(shape_type):
        match shape_type:
            case None:
                return None
            case "CIRCLE":
                return Circle()
            case "RECTANGLE":
                return Rectangle()
            case "SQAURE":
                return Square()
        return None

Here we have a Shape class which is getting inherited by many different classes, the Shape class has a method called draw, each subclass defines its own type of draw method. At the end we define a factory class which handles all the creation of objects. We can then use then use this:

ShapeFactory.get_shape("CIRCLE").draw()

Builder

Builder Pattern allows us to create objects step by step, simply by chaining methods, those methods return the modified instance.

class PersonBuilder:
    age = None
    name = None
    profession = None
    def __init__(self, age = None, name = None, profession = None):
        self.age = age
        self.name = name
        self.profession = profession

    def set_age(self, age: int):
        self.age = age
        return self

    def set_name(self, name: str):
        self.name = name
        return self

    def set_profession(self, profession: str):
        self.profession = profession
        return self
    def to_string(self) -> str:
        return f"name = {self.name}, profession = {self.profession}, age = {self.age}"

Pretty self-explanatory, we'll chain methods and get our object.

person = PersonBuilder().set_age(20).set_name("Jack").set_profession("Software Engineer")

Adapter

The Adapter Pattern allows a interface or class to be compatible to an incompatible one, for example a class takes jpg instead of png, the coversion from png to jpg will be done by the Adapter Pattern

class Ocean:
    pass

class Fish(Ocean):
    def swim(self):
        print("Swimming")

    def eat(self):
        print("Eat Eat")


class FishAdapter(Ocean):
    def swim(self):
        print("Swimming")

    def eat(self):
        print("Eat Eat")


class GoldFish(Fish):
    def __init__(self) -> None:
        super().__init__()


class RoboticComet(FishAdapter):
    def __init__(self) -> None:
        super().__init__()

So now we have Ocean class which is useless but is inherited by FishAdapter and Fish, lets first talk about Fish its a class which gives fishes their abilities, like ability to eat and swim, a real fish does that right?

On the other hand we have FishAdapter which makes a unreal fish like a plastic fish or robotic fish into a real one by giving it the ability to mimic the real fish's abilities

Going further we create two classes GoldFish which inherites Fish and RoboticFish which inherits FishAdapter, RoboticFish can't inherit Fish because thats what real fishes do and a RoboticFish isn't a real fish.

Let's see this in action

real_fish = GoldFish()
real_fish.swim()

plastic_fish = RoboticComet()
plastic_fish.eat()

Observer

This pattern is used to observe data and do some action. An Observable is a wrapper around data and when the data changes it reports the Observer which will do the action.

class Observer:
    def notify(self):
        print("Value changed")

class Observable:
    ob = []
    def __init__(self, value):
        self.value = value
    
    def subscribe(self, o: Observer):
        self.ob.append(o)
    
    def notify_ob(self):
        for o in self.ob:
            o.notify()
    
    def change_value(self, v):
        self.value = v
        self.notify_ob()

x = Observable("Haider")
watcher = Observer()
x.subscribe(watcher)
x.change_value("Blog Post")

Subscription is the relation or connection between observer and observable. You can see how the observable subscribes to the observer and then notifies it by calling its notify method.

Socials:

Support Me

GitHub

YouTube

Twitter