Вступ 3
Остання частина серії про шаблони проектування зосереджена на прикладах та практичних реалізаціях. Ми заглибимося в різні типи та принципи шаблонів проектування та розглянемо, як їх можна застосовувати у ваших проєктах.
Шаблони проектування в розробці програмного забезпечення
1. Створювальні шаблони (механізми створення об'єктів)
- Singleton (Одиничний об'єкт): Забезпечує створення лише одного екземпляра класу та надає глобальну точку доступу до нього.
- Factory Method (Фабричний метод): Створює об'єкти без вказівки точного класу для створення.
- Abstract Factory (Абстрактна фабрика): Надає інтерфейс для створення сімейств пов'язаних або залежних об'єктів без вказівки їх конкретних класів.
- Builder (Будівельник): Розділяє побудову складного об'єкта від його представлення.
- Prototype (Прототип): Створює нові об'єкти шляхом копіювання існуючого об'єкта, відомого як прототип.
2. Структурні шаблони (складання класів чи об'єктів)
- Adapter (Адаптер): Дозволяє несумісним інтерфейсам працювати разом.
- Bridge (Міст): Розділяє абстракцію об'єкта від його реалізації.
- Composite (Композиція): Складує об'єкти в деревоподібні структури для представлення ієрархій частина-ціле.
- Decorator (Декоратор): Додає нову функціональність об'єкту динамічно.
- Facade (Фасад): Надає спрощений інтерфейс до складної системи.
- Flyweight (Летючий вагон): Зменшує використання пам'яті, спільно використовуючи спільні частини стану між кількома об'єктами.
- Proxy (Проксі): Надає заступника для іншого об'єкта для контролю доступу до нього.
3. Поведінкові шаблони (комунікація між об'єктами)
- Chain of Responsibility (Цепочка відповідальностей): Пересилає запити вздовж ланцюга обробників.
- Command (Команда): Інкапсулює запит як об'єкт, дозволяючи параметризувати запити.
- Interpreter (Інтерпретатор): Визначає граматику для інтерпретації речень у мові.
- Iterator (Ітератор): Надає спосіб доступу до елементів колекції послідовно.
- Mediator (Посередник): Зменшує зв'язність між класами, централізуючи комунікацію.
- Memento (Мементо): Захоплює та відновлює внутрішній стан об'єкта.
- Observer (Спостерігач): Визначає залежність між об'єктами так, щоб коли один змінює стан, всі залежні отримують сповіщення.
- State (Стан): Дозволяє об'єкту змінювати свою поведінку при зміні внутрішнього стану.
- Strategy (Стратегія): Визначає родину алгоритмів, інкапсулює кожен з них і робить їх взаємозамінними.
- Template Method (Шаблонний метод): Визначає каркас алгоритму, відсуваючи кроки на підкласи.
- Visitor (Візитер): Додає нові операції до ієрархії класів без модифікації самих класів.
4. Шаблони для багатозадачності (управління багатопотоковими додатками)
- Active Object (Активний об'єкт): Відокремлює виконання методу від виклику методу.
- Balking (Пропуск): Перешкоджає виконанню операції, якщо об'єкт знаходиться в неправильному стані.
- Double-Checked Locking (Подвійна перевірка блокування): Зменшує накладні витрати при ініціалізації ресурсів у багатопотоковому середовищі.
- Guarded Suspension (Охоронюване призупинення): Керує операціями, які потребують виконання попередніх умов.
- Monitor Object (Об'єкт монітору): Синхронізує доступ до об'єкта між кількома потоками.
- Read-Write Lock (Блокування на читання-запис): Дозволяє кільком читачам або одному записувачу працювати одночасно.
- Thread Pool (Пул потоків): Керує пулом робочих потоків для ефективного оброблення кількох задач.
5.
Архітектурні шаблони (високорівневі структури програмних систем)
- Шарова архітектура (n-tier): Організовує систему в шари з конкретними обов'язками.
- Клієнт-сервер: Розділяє ролі клієнта та сервера.
- Майстер-слуга: Розділяє розподілені процеси на майстрів та слуг.
- Трубопровід і фільтр: Розбиває процеси на послідовність етапів обробки.
- Модель-вид-контролер (MVC): Розділяє завдання на модель, вид та контролер.
- Модель-вид-Модель перегляду (MVVM): Розділяє логіку та інтерфейс користувача, часто використовується в таких фреймворках, як WPF.
- Мікросервісна архітектура: Організовує додаток як набір малих, незалежних сервісів.
- Подієво-орієнтована архітектура: Використовує події для ініціювання комунікації між розслабленими сервісами.
- Архітектура на основі простору: Зменшує навантаження на бази даних за допомогою збереження даних у пам'яті.
- Архітектура орієнтована на сервіси (SOA): Створює системи з використанням повторно використовуваних сервісів.
6. Шаблони для хмарних та розподілених систем
- Запобіжник ланцюга: Перешкоджає повторному виконанню невдалих запитів.
- API Gateway: Діє як єдина точка входу для всіх мікросервісів.
- Сервісна сітка: Керує комунікацією між сервісами.
- Шаблон Сайдкар: Додає додаткову функціональність до сервісу без модифікації.
- Шаблон Сага: Керує розподіленими транзакціями за допомогою компенсуючих транзакцій.
- CQRS (Сегрегація команд та запитів): Розділяє команди від запитів.
- Подієвий джерело: Зберігає зміни стану як послідовність подій.
7. Шаблони інтеграції підприємств
- Агрегатор: Об'єднує кілька повідомлень в одне.
- Повідомлювач: Направляє повідомлення між сервісами.
- Черга повідомлень: Керує доставкою повідомлень між сервісами.
- Маршрутизатор на основі вмісту: Направляє повідомлення на основі їх вмісту.
- Канал Publish-Subscribe: Відправляє повідомлення кільком підписникам.
Тепер давайте заглибимося в практичні приклади цих шаблонів проектування на Python!
1.
Створювальні шаблони
Шаблон Singleton
Гарантує, що в класі існує лише один екземпляр, і надає глобальну точку доступу до цього екземпляра.
Приклад на Python:
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
# Використання
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # True
Шаблон Factory Method
Визначає інтерфейс для створення об'єктів, але дозволяє підкласам змінювати типи об'єктів, що будуть створені.
Приклад:
from abc import ABC, abstractmethod
class Product(ABC):
@abstractmethod
def operation(self):
pass
class ConcreteProductA(Product):
def operation(self):
return "Product A"
class ConcreteProductB(Product):
def operation(self):
return "Product B"
class Factory:
@staticmethod
def create_product(type_):
if type_ == "A":
return ConcreteProductA()
elif type_ == "B":
return ConcreteProductB()
raise ValueError("Unknown product type")
# Використання
product = Factory.create_product("A")
print(product.operation()) # "Product A"
Шаблон Abstract Factory
Надає інтерфейс для створення родин пов'язаних або залежних об'єктів.
Приклад:
class AbstractFactory(ABC):
@abstractmethod
def create_product(self):
pass
class ConcreteFactoryA(AbstractFactory):
def create_product(self):
return ConcreteProductA()
class ConcreteFactoryB(AbstractFactory):
def create_product(self):
return ConcreteProductB()
# Використання
factory = ConcreteFactoryA()
product = factory.create_product()
print(product.operation()) # "Product A"
Шаблон Builder
Розділяє процес створення об'єкта від його представленості.
Приклад:
class Product:
def __init__(self):
self.parts = []
def add(self, part):
self.parts.append(part)
def show(self):
print(", ".join(self.parts))
class Builder:
def build_part(self):
pass
class ConcreteBuilder(Builder):
def __init__(self):
self.product = Product()
def build_part(self):
self.product.add("Part A")
self.product.add("Part B")
def get_result(self):
return self.product
# Використання
builder = ConcreteBuilder()
builder.build_part()
product = builder.get_result()
product.show() # "Part A, Part B"
Шаблон Prototype
Створює об'єкти шляхом клонування існуючого об'єкта.
Приклад:
import copy
class Prototype:
def clone(self):
return copy.deepcopy(self)
class ConcretePrototype(Prototype):
def __init__(self, value):
self.value = value
# Використання
prototype = ConcretePrototype([1, 2, 3])
clone = prototype.clone()
print(clone.value) # [1, 2, 3]
2.
Структурні шаблони
Шаблон Adapter
Дозволяє несумісним інтерфейсам працювати разом.
Приклад:
class OldSystem:
def specific_request(self):
return "Old system output"
class Adapter:
def __init__(self, old_system):
self.old_system = old_system
def request(self):
return self.old_system.specific_request()
# Використання
adapter = Adapter(OldSystem())
print(adapter.request()) # "Old system output"
Шаблон Bridge
Розділяє абстракцію від реалізації.
Приклад:
class Implementation:
def operation(self):
pass
class ConcreteImplementationA(Implementation):
def operation(self):
return "ConcreteImplementationA"
class Abstraction:
def __init__(self, implementation):
self.implementation = implementation
def operation(self):
return self.implementation.operation()
# Використання
implementation = ConcreteImplementationA()
abstraction = Abstraction(implementation)
print(abstraction.operation()) # "ConcreteImplementationA"
Шаблон Decorator
Динамічно додає поведінку об'єктам.
Приклад:
class Component:
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 f"Decorator({self.component.operation()})"
# Використання
component = ConcreteComponent()
decorated = Decorator(component)
print(decorated.operation()) # "Decorator(ConcreteComponent)"
Шаблон Facade
Надає спрощений інтерфейс для складної підсистеми.
Приклад:
class SubsystemA:
def operation(self):
return "SubsystemA"
class SubsystemB:
def operation(self):
return "SubsystemB"
class Facade:
def __init__(self):
self.subsystemA = SubsystemA()
self.subsystemB = SubsystemB()
def operation(self):
return f"{self.subsystemA.operation()} + {self.subsystemB.operation()}"
# Використання
facade = Facade()
print(facade.operation()) # "SubsystemA + SubsystemB"
Поведінкові шаблони
Шаблон Observer
Дозволяє об'єктам сповіщати інші про зміни стану.
Приклад:
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def notify(self, message):
for observer in self._observers:
observer.update(message)
class Observer:
def update(self, message):
print(f"Observer received: {message}")
# Використання
subject = Subject()
observer = Observer()
subject.attach(observer)
subject.notify("Hello, World!") # "Observer received: Hello, World!"
Шаблон Command
Інкапсулює запит як об'єкт.
Приклад:
class Command:
def execute(self):
pass
class ConcreteCommand(Command):
def __init__(self, receiver):
self.receiver = receiver
def execute(self):
self.receiver.action()
class Receiver:
def action(self):
print("Action executed")
# Використання
receiver = Receiver()
command = ConcreteCommand(receiver)
command.execute() # "Action executed"
Шаблон State
Дозволяє об'єкту змінювати свою поведінку, коли змінюється його внутрішній стан.
Приклад:
class State:
def handle(self):
pass
class ConcreteStateA(State):
def handle(self):
return "State A"
class ConcreteStateB(State):
def handle(self):
return "State B"
class Context:
def __init__(self, state):
self.state = state
def request(self):
return self.state.handle()
# Використання
context = Context(ConcreteStateA())
print(context.request()) # "State A"
context.state = ConcreteStateB()
print(context.request()) # "State B"
## Поведінкові шаблони (продовження)
# Шаблон Chain of Responsibility
Передає запити по ланцюгу обробників.
## Приклад:
class Handler:
def init(self, successor=None):
self.successor = successor
def handlerequest(self, request):
if self.successor:
self.successor.handlerequest(request)
class ConcreteHandlerA(Handler):
def handlerequest(self, request):
if request == "A":
print("Handled by HandlerA")
else:
super().handlerequest(request)
class ConcreteHandlerB(Handler):
def handlerequest(self, request):
if request == "B":
print("Handled by HandlerB")
else:
super().handlerequest(request)
Використання
handlerchain = ConcreteHandlerA(ConcreteHandlerB())
handlerchain.handle_request("B") # "Handled by HandlerB"
```
Шаблон Mediator
Зменшує зв'язок між об'єктами, централізуючи комунікацію між ними.
ІНШУ ЧАСТИНУ МОЖНА ЗНАЙТИ ТУТ fzeba.com.
(Копіювання, вставка та виправлення 50 блоків коду в Medium - це занадто багато. Якщо вас цікавить ця тема та повний список шаблонів проектування, будь ласка, відвідайте мій особистий сайт для повної статті. ДЯКУЮ!)
Висновок
Тепер у вас є комплексний посібник з шаблонів архітектури програмного забезпечення, що включає:
- Шаблони створення: Singleton, Factory, Builder, Prototype
- Структурні шаблони: Adapter, Bridge, Composite, Decorator, Facade
- Поведінкові шаблони: Observer, Command, Strategy, State, Visitor
- Шаблони паралельності: Thread Pool, Read-Write Lock, Circuit Breaker
- Шаблони для хмарних обчислень: API Gateway, Saga, CQRS, Event Sourcing
- Шаблони інтеграції в підприємствах (EIP): Aggregator, Message Broker, Content-Based Router, Pub-Sub
Читайте цю статтю та інші на fzeba.com.
Перекладено з: Part 3/3 Basics of Software Architecture and Design Patterns