Skip to content

Instantly share code, notes, and snippets.

@andreafspeziale
Last active June 5, 2023 15:48
Show Gist options
  • Save andreafspeziale/e3af97217ea38e0b0cd7cb11493c38b4 to your computer and use it in GitHub Desktop.
Save andreafspeziale/e3af97217ea38e0b0cd7cb11493c38b4 to your computer and use it in GitHub Desktop.
Some design patterns ins Python

Design patterns refresh

Creational pattern

Factory

Class Burger:
  def __init__(self, ingredients):
    self.ingredients = ingredients

  def print(self):
    print(self.ingredients)

Class BurgerFactory:
  def createCheeseBurger(self):
    ingredients = ["bun", "cheese", "beef-patty"]
    return Burger(ingredients)

burgerFactory = BurgerFactory()
cheeseBurger = burgerFactory.createCheeseBurger().print()

Builder

Class Burger:
  def __init__(self):
    self.buns = None
    self.patty = None
    self.cheese = None

  def setBuns(self, bunStyle):
    self.buns = bunStyle

  def setPatty(self, pattyStyle):
    self.patty = pattyStyle

  def setCheese(self, cheeseStyle):
    self.cheese = cheeseStyle

Class BurgerBuilder:
  def __init__(self):
    self.burger = Burger()

  def addBuns(self, bunStyle):
      self.burger.setBuns(bunStyle)
      return self

  def addPatty(self, pattyStyle):
    self.burger.setPatty(pattyStyle)
    return self

  def addCheese(self, cheeseStyle):
    self.burger.setCheese(cheeseStyle)
    return self

  def build(self):
    return self.burger

burger = BurgerBuilder() \
  .addBuns("sesame") \
  .addPatty("fish-patty") \
  .addCheese("swiss cheese") \
  .build()

Singleton

Class that can only have a single instance of it that's instantiated. Shared source of true.

Class ApplicationState:
  instance = None

  def __init__(self):
    self.isLoggedIn = False

  @staticmethod
  def getAppState():
    if not ApplicationState.instance:
      ApplicationState.instance = ApplicationState()
    return ApplicationState.instance

appState1 = ApplicationState.getAppState()
print(appState1.isLoggedIn) # False

appState2 = ApplicationState.getAppState()
appState1.isLoggedIn = True

print(appState1.isLoggedIn) # True
print(appState2.isLoggedIn) # True

Behavioral Pattern

Observer

Class YoutubeChannel:
  def __init__(self, name):
    self.name = name
    self.subs = []

  def subscribe(self, sub):
    self.subs.append(sub)

  def notify(self, event):
    for sub in self.subs:
      sub.sendNotification(self.name, event)

from abc  import ABC, abstractmethod

class YoutubeSub(ABC):
  @abstractmethod
  def sendNotification(self, event):
    pass

class YoutubeUser(YoutubeSub):
  def __init__(self, name):
    self.name = name

  def sendNotification(self, channel, event):
    print(f"User: {self.name} received a notification from {channel}: {event}")

channel = YoutubeChannel("name")

channel.subscribe(YoutubeUser("u1"))
channel.subscribe(YoutubeUser("u2"))
channel.subscribe(YoutubeUser("u3"))

channel.notify("New video")

Iteratos

class ListNode:
  def __init__(self, val):
    self.val = val
    self.next = None

class LinkedList:
  def __init__(self, head):
    self.head = head
    self.cur = None

  def __iter__(self):
    self.cur = self.head
    return self

  def __next__(self):
    if self.cur:
      val = self.cur.val
      self.cur = self.cur.next
      return val
    else:
      raise StopIterator

head = ListNode(1)
head.next = ListNode(2)
head.next.next = ListNode(3)
myList = LinkedList(head)

for n in myList:
  print(n)

Strategy

from abc import ABC, abstractmethod

class FilterStrategy(ABC):

  @abstractmethod
  def removeValues(self, val):
    pass

class RemoveNegativeStrategy(FilterStrategy):
  def removeValues(self, val):
    return val < 0

class RemoveOddStrategy(FilterStrategy):
  def removeValues(self, val):
    return abs(val) % 2

class Values:
  def __init__(self, vals):
    self.vals = vals

  def filter(self, strategy):
    res = []
    for n in self.vals:
      if not strategy.removeValues(n):
        res.append(n)
    return res

values = Values([-1,3,4,5])
print(values.filter(RemoveNegativeStrategy()))

Structural pattern

Adapter

class USBCable:
  def __init__(self):
    self.isPlugged = False

  def plugUSB(self):
    self.isPlugged = True

class USBPort:
  def __init__(self):
    self.freePort = True

  def plug(self, usb):
    if self.freePort:
      usb.plugUSB()
      self.freePort = False

usbCable = USBCable()
usbPort1 = USBPort()
usbPort1.plug(usbCable)

class MicroUSBCable:
  def __init__(self):
    self.isPlugged = False

  def plugMicroUSB(self):
    self.isPlugged = True

class MicroToUSBAdapter(USBCable):
  def __init__(self, microUSBCable):
    self.microUSBCable = microUSBCable
    self.microUSBCable.plugMicroUSB()

microToUSBAdapter = MicroToUSBAdapter(MicroUSBCable())
usbPort2 = USBPort()
usbPort2.plug(microToUSBAdapter)

Facade

Wrapper class that can be used to abstract lower level details that we don't wanna have to worry about (e.g Http Client etc.).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment