Obiective
În această lecție, veți învăța:
- O introducere în arhitecturile de software
- Cele mai comune design patterns în Python
- Implementarea unor design patterns în Python
1. Introducere în arhitecturile de software
Arhitecturile de software reprezintă organizarea sistemelor de software și descriu modul în care componentele acestora interacționează. Ele sunt esențiale pentru a crea sisteme scalabile, maleabile și ușor de întreținut.
Un exemplu popular de arhitectură de software este Model-View-Controller (MVC), care separă componentele de afișare și control ale unei aplicații de logica de bază a acesteia. În Python, unele framework-uri web, cum ar fi Django, folosesc o abordare similară numită Model-View-Template (MVT).
2. Cele mai comune design patterns în Python
Design patterns sunt soluții generale reutilizabile la problemele comune întâlnite în proiectarea software-ului. Ele pot fi adaptate la nevoile specifice ale proiectului și pot ajuta la crearea unui cod mai eficient și ușor de întreținut. În continuare, vom explora câteva design patterns populare în Python.
2.1. Singleton
Singleton este un design pattern care asigură că o clasă are doar o singură instanță și oferă un punct de acces la aceasta. Acest lucru poate fi util pentru a coordona accesul la resurse partajate, cum ar fi conexiunile la baze de date.
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
class MyClass(Singleton):
pass
obj1 = MyClass()
obj2 = MyClass()
assert obj1 is obj2
2.2. Factory Method
Factory Method este un design pattern care oferă o interfață pentru crearea de obiecte într-o superclasă, dar permite subclaselor să decidă ce obiecte să creeze. Acesta poate fi util pentru a separa logica de construcție de cea de utilizare.
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
class AnimalFactory:
@staticmethod
def create_animal(animal_type):
if animal_type == "Dog":
return Dog()
elif animal_type == "Cat":
return Cat()
else:
raise ValueError("Invalid animal type")
animal = AnimalFactory.create_animal("Dog")
animal.speak() # Output: Woof!
2.3. Observer
Observer este un design pattern care oferă o interfață între obiecte, astfel încât când starea unui obiect se schimbă, toate obiectele dependente sunt notificate. Acesta poate fi util pentru a menține consistența între obiectele interconectate.
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self):
for observer in self._observers:
observer.update(self)
class ConcreteSubject(Subject):
def __init__(self):
super().__init__()
self._state = None
@property
def state(self):
return self._state
@state.setter
def state(self, value):
self._state = value
self.notify()
class Observer(ABC):
@abstractmethod
def update(self, subject):
pass
class ConcreteObserver(Observer):
def update(self, subject):
print(f"Observer: Subject's state is now {subject.state}")
subject = ConcreteSubject()
observer = ConcreteObserver()
subject.attach(observer)
subject.state = "new state" # Output: Observer: Subject's state is now new state
3. Implementarea unor designpatterns în Python
În această secțiune, vom implementa două design patterns suplimentare în Python: Decorator și Strategy.
3.1. Decorator
Decorator este un design pattern structural care permite adăugarea de funcționalități suplimentare unui obiect în mod dinamic, fără a afecta structura sa. Acesta poate fi util pentru a extinde comportamentul unor clase în mod flexibil și modular.
from abc import ABC, abstractmethod
class Component(ABC):
@abstractmethod
def operation(self):
pass
class ConcreteComponent(Component):
def operation(self):
return "ConcreteComponent"
class Decorator(Component):
def __init__(self, component):
self._component = component
def operation(self):
return self._component.operation()
class ConcreteDecoratorA(Decorator):
def operation(self):
return f"ConcreteDecoratorA({self._component.operation()})"
class ConcreteDecoratorB(Decorator):
def operation(self):
return f"ConcreteDecoratorB({self._component.operation()})"
component = ConcreteComponent()
decoratorA = ConcreteDecoratorA(component)
decoratorB = ConcreteDecoratorB(decoratorA)
print(decoratorB.operation()) # Output: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))
3.2. Strategy
Strategy este un design pattern care permite schimbarea comportamentului (strategiei) unui obiect la runtime. Acesta poate fi util pentru a decupla algoritmii de structurile de date pe care le utilizează.
from abc import ABC, abstractmethod
class Strategy(ABC):
@abstractmethod
def execute(self, data):
pass
class ConcreteStrategyA(Strategy):
def execute(self, data):
return sorted(data)
class ConcreteStrategyB(Strategy):
def execute(self, data):
return sorted(data, reverse=True)
class Context:
def __init__(self, strategy):
self._strategy = strategy
def set_strategy(self, strategy):
self._strategy = strategy
def execute_strategy(self, data):
return self._strategy.execute(data)
data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
context = Context(ConcreteStrategyA())
print(context.execute_strategy(data)) # Output: [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]
context.set_strategy(ConcreteStrategyB())
print(context.execute_strategy(data)) # Output: [9, 6, 5, 5, 5, 4, 3, 3, 2, 1, 1]
Concluzie
În această lecție, am discutat despre arhitecturile de software și am explorat câteva design patterns comune în Python. Aceste concepte sunt importante pentru a crea software scalabil, modular și ușor de întreținut. Continuați să experimentați și să aplicați aceste design patterns în proiectele dvs. pentru a vă îmbunătăți abilitățile de programare în Python.