В мире разработки программного обеспечения шаблоны проектирования играют решающую роль в создании надежного, удобного в сопровождении и масштабируемого кода. Они предоставляют проверенные решения распространенных проблем проектирования и помогают разработчикам писать код, который можно повторно использовать, модульный и простой для понимания. В этой статье мы рассмотрим три фундаментальные категории шаблонов проектирования: структурные, творческие и поведенческие шаблоны. Мы углубимся в каждую категорию, обсудим их назначение и предоставим примеры кода, иллюстрирующие их реализацию. Итак, начнём!
- Шаблоны структурного проектирования.
Шаблоны структурного проектирования направлены на организацию классов и объектов для формирования более крупных структур, сохраняя при этом гибкость и эффективность кода. Вот три популярных шаблона структурного проектирования:
a) Шаблон адаптера:
Шаблон адаптера позволяет несовместимым интерфейсам работать вместе. Он действует как мост между двумя несовместимыми классами, преобразуя интерфейс одного класса в другой интерфейс, ожидаемый клиентами. Этот шаблон особенно полезен при интеграции устаревшего кода или сторонних библиотек в ваше приложение.
Пример кода:
class Target:
def request(self):
pass
class Adaptee:
def specific_request(self):
pass
class Adapter(Target):
def __init__(self, adaptee):
self.adaptee = adaptee
def request(self):
self.adaptee.specific_request()
# Usage
adaptee = Adaptee()
adapter = Adapter(adaptee)
adapter.request()
b) Шаблон «Декоратор».
Шаблон «Декоратор» позволяет динамически добавлять к объекту новое поведение или обязанности. Он обеспечивает способ динамического добавления дополнительных функций к объекту без изменения его структуры. Этот шаблон полезен, когда вы хотите расширить функциональность объекта без создания подклассов.
Пример кода:
class Component:
def operation(self):
pass
class ConcreteComponent(Component):
def operation(self):
# Original operation implementation
pass
class Decorator(Component):
def __init__(self, component):
self.component = component
def operation(self):
self.component.operation()
# Usage
component = ConcreteComponent()
decorator = Decorator(component)
decorator.operation()
c) Шаблон фасада:
Шаблон фасада обеспечивает унифицированный интерфейс для набора интерфейсов в подсистеме. Он упрощает сложные подсистемы, предоставляя интерфейс более высокого уровня, который могут использовать клиенты. Этот шаблон полезен, когда вы хотите предоставить упрощенный интерфейс сложной системе или когда вам нужно отделить клиентский код от подсистемы.
Пример кода:
class Subsystem1:
def operation1(self):
pass
class Subsystem2:
def operation2(self):
pass
class Facade:
def __init__(self):
self.subsystem1 = Subsystem1()
self.subsystem2 = Subsystem2()
def operation(self):
self.subsystem1.operation1()
self.subsystem2.operation2()
# Usage
facade = Facade()
facade.operation()
- Шаблоны творческого проектирования.
Шаблоны творческого проектирования сосредоточены на механизмах создания объектов, обеспечивая гибкость и инкапсуляцию при создании объектов. Вот три часто используемых шаблона творческого проектирования:
a) Шаблон фабричного метода:
Шаблон фабричного метода предоставляет интерфейс для создания объектов, но позволяет подклассам решать, экземпляр какого класса создавать. Он инкапсулирует логику создания объектов и предоставляет возможность делегировать создание экземпляров подклассам. Этот шаблон полезен, когда вы хотите отделить клиентский код от конкретных классов, которые он создает.
Пример кода:
class Product:
def operation(self):
pass
class ConcreteProductA(Product):
def operation(self):
# Implementation for Product A
pass
class ConcreteProductB(Product):
def operation(self):
# Implementation for Product B
pass
class Creator:
def factory_method(self):
pass
class ConcreteCreatorA(Creator):
def factory_method(self):
return ConcreteProductA()
class ConcreteCreatorB(Creator):
def factory_method(self):
return ConcreteProductB()
# Usage
creator = ConcreteCreatorA()
product = creator.factory_method()
product.operation()
b) Шаблон Singleton:
Шаблон Singleton гарантирует, что класс имеет только один экземпляр, и обеспечивает глобальный доступ к этому экземпляру. Это полезно, когда вам нужно ограничить создание экземпляра класса одним объектом, например соединением с базой данных или регистратором.
Пример кода:
class Singleton:
_instance = None
@staticmethod
def get_instance():
if not Singleton._instance:
Singleton._instance = Singleton()
return Singleton._instance
# Usage
singleton = Singleton.get_instance()
c) Шаблон Builder:
Шаблон Builder отделяет построение сложных объектов от их представления, позволяя одному и тому же процессу конструирования создавать разные представления. Он обеспечивает пошаговый подход к созданию объектов, позволяя лучше контролировать процесс строительства. Этот шаблон полезен, когда вам нужно создать сложные объекты с разными конфигурациями.
Пример кода:
class Product:
def __init__(self):
self.part1 = None
self.part2 = None
class Builder:
def build_part1(self):
pass
def build_part2(self):
pass
def get_product(self):
pass
class ConcreteBuilder(Builder):
def __init__(self):
self.product = Product()
def build_part1(self):
self.product.part1 = "Part 1"
def build_part2(self):
self.product.part2 = "Part 2"
def get_product(self):
return self.product
class Director:
def __init__(self, builder):
self.builder = builder
def construct(self):
self.builder.build_part1()
self.builder.build_part2()
# Usage
builder = ConcreteBuilder()
director = Director(builder)
director.construct()
product = builder.get_product()
- Шаблоны поведенческого проектирования.
Шаблоны поведенческого проектирования фокусируются на взаимодействии между объектами, определяя, как они взаимодействуют и распределяют обязанности. Вот три широко используемых шаблона поведенческого проектирования:
a) Шаблон наблюдателя:
Шаблон наблюдателя устанавливает зависимость «один ко многим» между объектами, при которой изменения в одном объекте вызывают обновления в зависимых объектах. Он позволяет объектам автоматически уведомляться и обновляться при изменении состояния другого объекта.
Пример кода:
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()
class Observer:
def update(self):
pass
class ConcreteSubject(Subject):
def __init__(self):
super().__init__()
self.state = None
def set_state(self, state):
self.state = state
self.notify()
class ConcreteObserver(Observer):
def update(self):
# Update logic based on the subject's state
pass
# Usage
subject = ConcreteSubject()
observer = ConcreteObserver()
subject.attach(observer)
subject.set_state("New State")
b) Шаблон стратегии:
Шаблон стратегии определяет семейство взаимозаменяемых алгоритмов и инкапсулирует каждый алгоритм, позволяя использовать их взаимозаменяемо. Он позволяет динамически выбирать различные алгоритмы во время выполнения в зависимости от контекста или требований.
Пример кода:
class Context:
def __init__(self, strategy):
self.strategy = strategy
def set_strategy(self, strategy):
self.strategy = strategy
def execute_strategy(self):
self.strategy.execute()
class Strategy:
def execute(self):
pass
class ConcreteStrategyA(Strategy):
def execute(self):
# Implementation for Strategy A
pass
class ConcreteStrategyB(Strategy):
def execute(self):
# Implementation for Strategy B
pass
# Usage
strategy_a = ConcreteStrategyA()
context = Context(strategy_a)
context.execute_strategy()
strategy_b = ConcreteStrategyB()
context.set_strategy(strategy_b)
context.execute_strategy()
c) Шаблон команды:
Шаблон команды инкапсулирует запрос как объект, тем самым позволяя пользователям параметризовать клиентов с помощью очередей, запросов или операций. Он отделяет отправителя запроса от получателя, обеспечивая гибкость в обработке запросов.
Пример кода:
class Receiver:
def action(self):
pass
class Command:
def __init__(self, receiver):
self.receiver = receiver
def execute(self):
pass
class ConcreteCommand(Command):
def execute(self):
self.receiver.action()
class Invoker:
def __init__(self):
self.command = None
def set_command(self, command):
self.command = command
def execute_command(self):
self.command.execute()
# Usage
receiver = Receiver()
command = ConcreteCommand(receiver)
invoker = Invoker()
invoker.set_command(command)
invoker.execute_command()
Шаблоны проектирования – бесценные инструменты разработки программного обеспечения, обеспечивающие возможность многократного использования решений распространенных проблем проектирования. В этой статье мы исследовали три категории шаблонов проектирования: структурные, творческие и поведенческие шаблоны. Мы обсудили их назначение, предоставили примеры кода и продемонстрировали, как их можно реализовать в реальных сценариях. Понимая и применяя эти шаблоны проектирования, разработчики могут значительно повысить качество, удобство сопровождения и масштабируемость своего кода.