На какие три основные группы делятся классические паттерны проектирования (GoF)?

Ответ

Классические паттерны проектирования, описанные в книге "банды четырех" (GoF), делятся на три основные категории в зависимости от их назначения:

  1. Порождающие (Creational) Отвечают за процессы создания объектов, позволяя сделать систему независимой от способа их создания и представления. Они помогают создавать объекты гибко и в контролируемых условиях.

    • Примеры: Singleton (Одиночка), Factory Method (Фабричный метод), Abstract Factory (Абстрактная фабрика), Builder (Строитель), Prototype (Прототип).
  2. Структурные (Structural) Определяют, как из классов и объектов формировать более крупные и сложные структуры, сохраняя их гибкость и эффективность. Они упрощают структуру, идентифицируя отношения между сущностями.

    • Примеры: Adapter (Адаптер), Decorator (Декоратор), Facade (Фасад), Proxy (Заместитель), Composite (Компоновщик), Bridge (Мост).
  3. Поведенческие (Behavioral) Отвечают за эффективное взаимодействие и распределение обязанностей между объектами. Они определяют шаблоны коммуникации между объектами.

    • Примеры: Observer (Наблюдатель), Strategy (Стратегия), Command (Команда), Iterator (Итератор), State (Состояние), Chain of Responsibility (Цепочка обязанностей).

Пример порождающего паттерна (Singleton):

Этот паттерн гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к нему.

class DatabaseConnection:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            print("Создание нового подключения к БД...")
            cls._instance = super().__new__(cls)
        return cls._instance

    def connect(self):
        print("Подключение установлено.")

# Использование
db1 = DatabaseConnection()
db2 = DatabaseConnection()

print(db1 is db2)  # Выведет: True, т.к. это один и тот же объект
db1.connect()

Ответ 18+ 🔞

А, паттерны проектирования, эти ёбаные классические штуки от "банды четырёх"! Ну, типа, как в том анекдоте про Муму — их тоже можно по пачкам разложить, чтобы не путаться, блядь. Слушай, смотри, как они там всё по полочкам разложили, овердохуища какая система!

В общем, вся эта ихняя мудя делится на три большие кучи, как говно в сортире: порождающие, структурные и поведенческие. Каждая со своим приколом.

  1. Порождающие (Creational) Ну, это те, которые отвечают за то, как объекты на свет появляются, блядь. Чтобы не просто new SomeClass() тыкать, а с умом, гибко и под контролем. Типа, чтоб система не зависела от того, как именно эту хуйню создают. Представь, ты не просто собаку заводишь, а по патенту, с родословной, чтобы точно Муму получилась, а не какой-нибудь шавки-переростка.

    • Примеры, блядь: Singleton (Одиночка — чтоб один был и всё), Factory Method (Фабричный метод — типа конвейер), Abstract Factory (Абстрактная фабрика — целый завод, ёпта), Builder (Строитель — по кирпичику), Prototype (Прототип — клонировал и пошёл).
  2. Структурные (Structural) А вот эти уже про то, как из этих самых объектов, как из кубиков Лего, собрать что-то большое и сложное, но чтобы не развалилось и не выглядело как пиздец. Чтоб всё друг к другу подходило, как Герасим к своей каморке.

    • Примеры: Adapter (Адаптер — чтоб вилка в розетку влезла, даже если дырки не те), Decorator (Декоратор — как слоями гипсокартон обшиваешь, функционал добавляешь), Facade (Фасад — одна красивая дверь вместо кучи проводов и труб), Proxy (Заместитель — типа секретарь, который решает, пускать тебя к боссу или нет).
  3. Поведенческие (Behavioral) Ну а это уже про общение, блядь! Кто кому что говорит, кто за что отвечает, как команды передаются. Чтобы объекты не как немые Герасимы были, а нормально между собой договаривались, распределяли обязанности. Чтоб не было, что один всё делает, а остальные пальцем охуевают.

    • Примеры: Observer (Наблюдатель — один крикнул "Муму!", все на уши встали), Strategy (Стратегия — можно драться кулаком, а можно — кирпичом, главное подход выбрать), Command (Команда — завернул действие в бумажку, отдал — пусть выполняют), Iterator (Итератор — чтобы по списку пройтись, как по бутылкам).

Ну и примерчик, чтобы не быть пиздаболом. Вот тебе порождающий паттерн — Одиночка (Singleton):

Смысл в том, что этот класс — как последняя бутылка в деревне. Одна на всех. Хоть сто раз пытайся создать — получишь одну и ту же, блядь. Глобальная точка доступа, ёпта!

class DatabaseConnection:
    _instance = None  # Вот тут она, наша одна-единственная, лежит

    def __new__(cls, *args, **kwargs):
        if not cls._instance:  # Если ещё ни разу не создавали — охуенно!
            print("Создание нового подключения к БД...")
            cls._instance = super().__new__(cls)  # Вот тут родили
        return cls._instance  # А если уже есть — на, получай старую, не жадничай

    def connect(self):
        print("Подключение установлено.")

# Использование
db1 = DatabaseConnection()  # Создали
db2 = DatabaseConnection()  # Думали, создали, а по факту — ту же самую дали

print(db1 is db2)  # Выведет: True, потому что это один и тот же объект, пиздец!
db1.connect()

Вот и вся магия, блядь. Создаётся один раз, а потом все как собаки на неё смотрят. Удобно, но если переборщить — получится глобальная переменная в красивой обёртке, а это уже, знаешь, волнение ебать.