200 вопросов по паттернам проектирования
200 вопросов по паттернам проектирования
Основы паттернов проектирования
Вопрос
Что такое паттерн проектирования?
Ответ
Паттерн проектирования — это проверенное решение типовой проблемы проектирования программного обеспечения. Он описывает взаимодействие классов и объектов, не привязываясь к конкретной реализации, а фокусируясь на структуре и отношениях между компонентами.
Вопрос
Какова цель использования паттернов проектирования?
Ответ
Цель паттернов проектирования — повысить читаемость, сопровождаемость и повторное использование кода, а также ускорить процесс разработки за счёт применения уже проверенных решений.
Вопрос
Кто впервые систематизировал паттерны проектирования?
Ответ
Группа авторов, известная как "Банда четырёх" (Gang of Four, GoF): Эрих Гамма, Ричард Хелм, Ральф Джонсон и Джон Влиссидес. Их книга "Приёмы объектно-ориентированного проектирования. паттерны проектирования" вышла в 1994 году.
Вопрос
На какие три категории делятся паттерны проектирования по классификации GoF?
Ответ
Паттерны делятся на порождающие, структурные и поведенческие.
Вопрос
Что решают порождающие паттерны?
Ответ
Порождающие паттерны решают задачи создания объектов, делая этот процесс гибким и независимым от конкретных классов.
Вопрос
Что решают структурные паттерны?
Ответ
Структурные паттерны обеспечивают составление объектов и классов в более крупные структуры, сохраняя при этом гибкость и эффективность.
Вопрос
Что решают поведенческие паттерны?
Ответ
Поведенческие паттерны определяют способы взаимодействия и распределения обязанностей между объектами.
Вопрос
Что означает принцип "программируй на уровне интерфейсов, а не реализаций"?
Ответ
Этот принцип означает, что код должен зависеть от абстракций (интерфейсов или абстрактных классов), а не от конкретных реализаций, что повышает гибкость и упрощает замену компонентов.
Вопрос
Как паттерны связаны с принципами SOLID?
Ответ
паттерны проектирования часто реализуют или поддерживают принципы SOLID. Например, паттерн Стратегия поддерживает принцип открытости/закрытости, а паттерн Зависимость от абстракции — принцип инверсии зависимостей.
Вопрос
Может ли один паттерн относиться к нескольким категориям?
Ответ
Нет. Каждый паттерн из классического каталога GoF принадлежит ровно одной категории: порождающей, структурной или поведенческой.
Вопрос
Что такое анти-паттерн?
Ответ
Анти-паттерн — это распространённое, но неэффективное или контрпродуктивное решение проектной задачи, которое ведёт к ухудшению качества кода.
Вопрос
Обязательно ли использовать паттерны в каждом проекте?
Ответ
Нет. Паттерны следует применять только тогда, когда они действительно решают существующую проблему. Принудительное использование паттернов без необходимости усложняет код.
Вопрос
Как отличить правильное применение паттерна от его злоупотребления?
Ответ
Правильное применение упрощает архитектуру, делает код понятнее и гибче. Злоупотребление проявляется в избыточной абстракции, усложнении чтения кода и решении несуществующих проблем.
Вопрос
Что такое шаблон проектирования и чем он отличается от паттерна?
Ответ
Термины часто используются как синонимы. Однако шаблон может относиться к более широкому контексту, включая архитектурные решения, тогда как паттерн проектирования обычно ограничен уровнем классов и объектов.
Вопрос
Можно ли создавать собственные паттерны?
Ответ
Да. Если разработчик сталкивается с повторяющейся проблемой и находит обобщённое решение, он может зафиксировать его как собственный паттерн, если оно соответствует критериям повторного использования и обобщения.
Вопрос
Как паттерны влияют на тестируемость кода?
Ответ
Паттерны повышают тестируемость, так как способствуют слабой связанности и зависимости от абстракций, что упрощает подмену компонентов моками или заглушками.
Вопрос
Что такое контекст применения паттерна?
Ответ
Контекст применения — это совокупность условий, при которых паттерн оказывается полезным. Он включает тип проблемы, ограничения системы и цели проектирования.
Вопрос
Как документируется паттерн проектирования?
Ответ
Классическая документация паттерна включает: название, цель, мотивацию, структуру, участников, взаимодействие, последствия, варианты реализации и примеры кода.
Вопрос
Почему паттерны не зависят от языка программирования?
Ответ
Паттерны описывают концептуальные решения на уровне архитектуры и взаимодействия компонентов. Хотя реализация может различаться, сама идея остаётся неизменной.
Вопрос
Какие языковые особенности могут делать некоторые паттерны избыточными?
Ответ
В языках с функциями первого класса (например, JavaScript, Python) паттерны типа Стратегия или Команда могут быть реализованы проще через передачу функций. В языках с мощной системой метапрограммирования (например, Ruby) могут исчезать потребности в паттернах типа Фабрика.
Порождающие паттерны
Вопрос
Что решают порождающие паттерны проектирования?
Ответ
Порождающие паттерны решают задачи создания объектов, делая этот процесс гибким, инкапсулированным и независимым от конкретных классов.
Вопрос
Какие основные порождающие паттерны описаны в книге GoF?
Ответ
Основные порождающие паттерны: Фабричный метод, Абстрактная фабрика, Строитель, Одиночка и Прототип.
Вопрос
В чём суть паттерна "Одиночка" (Singleton)?
Ответ
Паттерн Одиночка гарантирует, что у класса существует только один экземпляр, и предоставляет глобальную точку доступа к нему.
Вопрос
Приведите пример реализации паттерна Одиночка на C#.
Ответ
public sealed class Singleton
{
private static readonly Singleton _instance = new();
private Singleton() { }
public static Singleton Instance => _instance;
}
Эта реализация потокобезопасна благодаря статической инициализации и запечатанному классу.
Вопрос
Приведите пример реализации паттерна Одиночка на Java.
Ответ
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
Конструктор приватный, экземпляр создаётся один раз при загрузке класса.
Вопрос
Приведите пример реализации паттерна Одиночка на Python.
Ответ
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
Метод __new__ контролирует создание единственного экземпляра.
Вопрос
Какие проблемы может вызывать использование паттерна Одиночка?
Ответ
Одиночка нарушает принцип единственной ответственности, усложняет тестирование из-за глобального состояния и затрудняет параллельное выполнение, если реализация не потокобезопасна.
Вопрос
Что такое паттерн "Прототип" (Prototype)?
Ответ
Паттерн Прототип позволяет создавать новые объекты путём копирования существующего объекта-прототипа, а не через конструктор.
Вопрос
Какой интерфейс используется в Java для реализации паттерна Прототип?
Ответ
Интерфейс Cloneable. Класс должен реализовать этот интерфейс и переопределить метод clone().
Вопрос
Почему в Python часто достаточно использовать copy.copy() или copy.deepcopy() вместо явного паттерна Прототип?
Ответ
Потому что модуль copy предоставляет встроенные механизмы клонирования объектов, что делает явную реализацию паттерна избыточной в большинстве случаев.
Вопрос
Что такое паттерн "Строитель" (Builder)?
Ответ
Паттерн Строитель разделяет конструирование сложного объекта от его представления, позволяя использовать один и тот же процесс построения для создания различных представлений.
Вопрос
В каких случаях применяется паттерн Строитель?
Ответ
Строитель применяется, когда объект имеет множество опциональных параметров, когда этапы создания логически разделимы, или когда требуется гарантировать корректное состояние объекта после построения.
Вопрос
Приведите пример использования паттерна Строитель в Java.
Ответ
public class Pizza {
private String dough, sauce, topping;
private Pizza(Builder builder) {
this.dough = builder.dough;
this.sauce = builder.sauce;
this.topping = builder.topping;
}
public static class Builder {
private String dough, sauce, topping;
public Builder setDough(String dough) { this.dough = dough; return this; }
public Builder setSauce(String sauce) { this.sauce = sauce; return this; }
public Builder setTopping(String topping) { this.topping = topping; return this; }
public Pizza build() { return new Pizza(this); }
}
}
// Использование:
Pizza pizza = new Pizza.Builder().setDough("thin").setSauce("tomato").build();
Вопрос
Что такое паттерн "Фабричный метод" (Factory Method)?
Ответ
Паттерн Фабричный метод определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанцировать.
Вопрос
Какова основная цель паттерна Фабричный метод?
Ответ
Основная цель — делегировать создание объектов подклассам, обеспечивая расширяемость без изменения клиентского кода.
Вопрос
Приведите пример паттерна Фабричный метод на C#.
Ответ
public abstract class Creator
{
public abstract IProduct FactoryMethod();
}
public class ConcreteCreator : Creator
{
public override IProduct FactoryMethod() => new ConcreteProduct();
}
public interface IProduct { }
public class ConcreteProduct : IProduct { }
Вопрос
Чем отличается паттерн "Абстрактная фабрика" от "Фабричного метода"?
Ответ
Фабричный метод создаёт один тип продукта через наследование, тогда как Абстрактная фабрика создаёт семейства связанных или зависимых объектов без указания их конкретных классов.
Вопрос
Что такое паттерн "Абстрактная фабрика" (Abstract Factory)?
Ответ
Паттерн Абстрактная фабрика предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов без указания их конкретных классов.
Вопрос
Приведите пример ситуации, где уместна Абстрактная фабрика.
Ответ
Создание UI-компонентов для разных операционных систем: кнопки, поля ввода и меню должны соответствовать стилю Windows, macOS или Linux. Абстрактная фабрика позволяет выбрать всю тему целиком.
Вопрос
Как реализуется паттерн Абстрактная фабрика на Python?
Ответ
from abc import ABC, abstractmethod
class Button(ABC):
@abstractmethod
def render(self): pass
class WindowsButton(Button):
def render(self): return "Windows Button"
class MacButton(Button):
def render(self): return "Mac Button"
class GUIFactory(ABC):
@abstractmethod
def create_button(self) -> Button: pass
class WindowsFactory(GUIFactory):
def create_button(self) -> Button: return WindowsButton()
class MacFactory(GUIFactory):
def create_button(self) -> Button: return MacButton()
Вопрос
Можно ли комбинировать паттерны Строитель и Абстрактная фабрика?
Ответ
Да. Абстрактная фабрика может создавать различные строители, каждый из которых собирает сложный объект в соответствии с правилами конкретного семейства.
Вопрос
Как паттерн Прототип помогает избежать дорогостоящего создания объекта?
Ответ
Прототип позволяет клонировать уже существующий, полностью инициализированный объект, что дешевле, чем повторно выполнять сложную логику инициализации.
Вопрос
Что такое "глубокое копирование" в контексте паттерна Прототип?
Ответ
Глубокое копирование — это создание новой копии объекта вместе со всеми вложенными объектами, а не только поверхностное копирование ссылок.
Вопрос
Почему Одиночка считается антипаттерном в некоторых кругах?
Ответ
Потому что он вводит глобальное состояние, усложняет модульное тестирование и нарушает инверсию зависимостей, делая код менее гибким и более связанным.
Вопрос
Как обеспечить потокобезопасность в паттерне Одиночка на Java?
Ответ
Можно использовать статический инициализатор (как в примере выше), либо применить двойную проверку блокировки (double-checked locking) с ключевым словом volatile.
Вопрос
Что такое "ленивая инициализация" в контексте Одиночки?
Ответ
Ленивая инициализация — это создание экземпляра только в момент первого обращения к нему, а не при загрузке класса.
Вопрос
Какие языковые конструкции могут заменять паттерн Одиночка?
Ответ
В языках с поддержкой модулей (например, Python, JavaScript) сам модуль может служить одиночкой. В C# можно использовать статические классы, хотя они менее гибкие.
Вопрос
Может ли паттерн Строитель возвращать неизменяемый объект?
Ответ
Да. Часто строитель создаёт неизменяемый объект на этапе build(), чтобы гарантировать целостность состояния после построения.
Вопрос
Как паттерн Фабричный метод поддерживает принцип открытости/закрытости?
Ответ
Он позволяет расширять функциональность системы добавлением новых подклассов без изменения существующего кода, использующего фабрику.
Вопрос
Что такое "фабрика" в общем смысле?
Ответ
Фабрика — это компонент, отвечающий за создание других объектов, инкапсулируя логику выбора и инициализации.
Вопрос
В чём разница между простой фабрикой и паттерном Фабричный метод?
Ответ
Простая фабрика — это вспомогательный класс с условной логикой создания, тогда как Фабричный метод — полноценный паттерн, использующий наследование для делегирования создания подклассам.
Вопрос
Как паттерн Абстрактная фабрика способствует слабой связанности?
Ответ
Клиентский код зависит только от абстрактных интерфейсов фабрики и продуктов, а не от конкретных реализаций, что упрощает замену семейств объектов.
Вопрос
Можно ли использовать паттерн Прототип для создания объектов с изменяемым состоянием?
Ответ
Да, но необходимо реализовать корректное глубокое копирование, чтобы изменения в клоне не влияли на исходный прототип.
Вопрос
Какие преимущества даёт паттерн Строитель при работе с необязательными параметрами?
Ответ
Он устраняет необходимость в многочисленных конструкторах или сеттерах, предоставляя читаемый и последовательный API для настройки объекта.
Вопрос
Что такое "директор" в паттерне Строитель?
Ответ
Директор — это дополнительный класс, который инкапсулирует процесс построения, вызывая методы строителя в определённом порядке для получения стандартной конфигурации.
Вопрос
Обязателен ли директор в паттерне Строитель?
Ответ
Нет. Директор полезен для стандартизации, но клиент может напрямую управлять строителем, если нужна гибкость.
Вопрос
Как паттерн Прототип связан с интерфейсом ICloneable в C#?
Ответ
Интерфейс ICloneable объявляет метод Clone(), который может использоваться для реализации паттерна Прототип, хотя его применение сегодня считается устаревшим из-за отсутствия различия между поверхностным и глубоким копированием.
Вопрос
Почему в современных языках паттерн Прототип используется реже?
Ответ
Потому что встроенные механизмы сериализации/десериализации или функции клонирования (например, в Python или JavaScript) часто проще и надёжнее.
Вопрос
Как паттерн Одиночка влияет на жизненный цикл объекта?
Ответ
Он привязывает жизненный цикл объекта ко времени выполнения программы: объект создаётся при первом обращении и живёт до завершения работы приложения.
Вопрос
Можно ли иметь несколько одиночек одного типа в одном приложении?
Ответ
Нет. По определению паттерна, должен существовать ровно один экземпляр класса в пределах области видимости.
Вопрос
Как паттерн Абстрактная фабрика помогает при тестировании?
Ответ
Он позволяет легко подменить реальные фабрики на моки, создавая заглушки для всех зависимых объектов одним действием.
Вопрос
Что происходит, если в паттерне Строитель вызвать build() несколько раз?
Ответ
Каждый вызов build() должен возвращать новый объект, чтобы избежать неожиданного совместного использования состояния.
Вопрос
Как паттерн Фабричный метод связан с полиморфизмом?
Ответ
Он использует полиморфизм: клиент вызывает фабричный метод через базовый интерфейс, но получает объект конкретного подтипа, определяемого реализацией подкласса.
Вопрос
Может ли паттерн Прототип использоваться для кэширования?
Ответ
Да. Прототипы могут храниться в пуле и клонироваться по запросу, что эффективно для часто создаваемых тяжёлых объектов.
Вопрос
Какие недостатки у паттерна Абстрактная фабрика?
Ответ
Он усложняет расширение: добавление нового типа продукта требует изменения всех существующих фабрик, что нарушает принцип открытости/закрытости.
Вопрос
Как паттерн Строитель улучшает читаемость кода?
Ответ
Он заменяет длинные списки параметров или цепочки сеттеров на последовательные вызовы методов с понятными именами, формируя DSL-подобный стиль.
Вопрос
Что такое "флуент-интерфейс" и как он связан со Строителем?
Ответ
Флуент-интерфейс — это стиль API, где методы возвращают this, позволяя вызывать их цепочкой. Строитель часто реализует флуент-интерфейс для удобства настройки.
Вопрос
Как паттерн Одиночка может быть реализован с использованием перечисления в Java?
Ответ
public enum Singleton {
INSTANCE;
public void doSomething() { /* ... */ }
}
Это наиболее краткий и потокобезопасный способ, рекомендованный Джошуа Блохом.
Вопрос
Почему паттерн Прототип особенно полезен в играх?
Ответ
Потому что игровые объекты (враги, предметы) часто создаются массово с небольшими вариациями, и клонирование прототипа быстрее, чем повторная инициализация.
Вопрос
Как паттерн Фабричный метод помогает при работе с плагинами?
Ответ
Он позволяет загружать и создавать экземпляры классов из внешних сборок, не зная их имён на этапе компиляции, через общий интерфейс.
Вопрос
Можно ли применять паттерн Абстрактная фабрика к необъектным языкам?
Ответ
Да, если язык поддерживает функции высшего порядка. Например, в Python фабрика может быть функцией, возвращающей словарь функций-конструкторов.
Вопрос
Какие альтернативы паттерну Одиночка существуют для управления общим состоянием?
Ответ
Инъекция зависимостей, сервис-локатор, передача контекста явно или использование модуля как пространства имён с состоянием.
Вопрос
Как паттерн Строитель помогает при валидации объекта?
Ответ
Он позволяет отложить валидацию до вызова build(), проверяя, что все обязательные поля установлены и состояние согласовано.
Вопрос
Что делать, если клонирование в паттерне Прототип невозможно?
Ответ
Тогда паттерн неприменим. Альтернатива — использовать фабрику или сериализацию, если объект поддерживает её.
Вопрос
Как паттерн Абстрактная фабрика связан с принципом инверсии зависимостей?
Ответ
Он реализует этот принцип: высокоуровневые модули зависят от абстракций (интерфейсов фабрики), а не от деталей (конкретных классов).
Струкурные паттерны
Вопрос
Что решают структурные паттерны проектирования?
Ответ
Структурные паттерны решают задачи компоновки классов и объектов в более крупные структуры, сохраняя при этом гибкость и эффективность взаимодействия.
Вопрос
Какие основные структурные паттерны описаны в книге GoF?
Ответ
Основные структурные паттерны: Адаптер, Мост, Компоновщик, Декоратор, Фасад, Приспособленец (Flyweight) и Заместитель (Proxy).
Вопрос
Что такое паттерн "Адаптер" (Adapter)?
Ответ
Паттерн Адаптер преобразует интерфейс одного класса к другому интерфейсу, ожидаемому клиентом, позволяя совместно использовать классы, которые иначе были бы несовместимы.
Вопрос
Приведите пример применения паттерна Адаптер.
Ответ
Интеграция сторонней библиотеки для работы с платежами, которая использует собственный интерфейс, в систему, ожидающую единый интерфейс IPaymentProcessor. Адаптер реализует IPaymentProcessor, делегируя вызовы библиотеке.
Вопрос
Как реализуется паттерн Адаптер на уровне классов?
Ответ
Классический адаптер наследует целевой интерфейс и содержит экземпляр адаптируемого класса, к которому делегирует вызовы после преобразования сигнатур.
Вопрос
Что такое объектный адаптер?
Ответ
Объектный адаптер использует композицию: он содержит ссылку на адаптируемый объект и реализует целевой интерфейс, преобразуя вызовы.
Вопрос
Что такое классовый адаптер?
Ответ
Классовый адаптер использует множественное наследование: он наследует одновременно и целевой интерфейс, и адаптируемый класс. Такой подход возможен только в языках с поддержкой множественного наследования.
Вопрос
Приведите пример паттерна Адаптер на Python.
Ответ
class LegacyPrinter:
def print_document(self, text):
return f"[Legacy] {text}"
class ModernPrinterInterface:
def print(self, content): pass
class PrinterAdapter(ModernPrinterInterface):
def __init__(self, legacy_printer):
self._legacy = legacy_printer
def print(self, content):
return self._legacy.print_document(content)
Вопрос
Что такое паттерн "Мост" (Bridge)?
Ответ
Паттерн Мост разделяет абстракцию от её реализации, чтобы их можно было изменять независимо.
Вопрос
В чём разница между паттернами Мост и Адаптер?
Ответ
Адаптер применяется после проектирования для совместимости существующих интерфейсов, тогда как Мост закладывается заранее для разделения абстракции и реализации.
Вопрос
Приведите пример использования паттерна Мост.
Ответ
Графическая библиотека, где форма (окружность, прямоугольник) — это абстракция, а рендерер (OpenGL, DirectX) — реализация. Мост позволяет комбинировать любую форму с любым рендерером.
Вопрос
Как паттерн Мост упрощает расширение системы?
Ответ
Он позволяет добавлять новые виды абстракций и новые реализации независимо друг от друга, без изменения существующего кода.
Вопрос
Что такое паттерн "Компоновщик" (Composite)?
Ответ
Паттерн Компоновщик позволяет сгруппировать объекты в древовидные структуры для представления иерархий часть-целое, при этом клиенты могут единообразно работать с отдельными объектами и составными.
Вопрос
Приведите пример применения паттерна Компоновщик.
Ответ
Дерево файловой системы: файлы и папки реализуют общий интерфейс, например, FileSystemItem, с методом getSize(). Папка рекурсивно суммирует размеры своих элементов.
Вопрос
Какие два типа компонентов выделяются в паттерне Компоновщик?
Ответ
Лист (Leaf) — конечный элемент, не имеющий потомков. Узел (Composite) — составной элемент, содержащий другие компоненты.
Вопрос
Что такое паттерн "Декоратор" (Decorator)?
Ответ
Паттерн Декоратор динамически добавляет объекту новую функциональность, оборачивая его в другой объект, реализующий тот же интерфейс.
Вопрос
В чём преимущество Декоратора перед наследованием?
Ответ
Декоратор позволяет добавлять поведение во время выполнения и комбинировать несколько декораторов, избегая взрывного роста подклассов.
Вопрос
Приведите пример паттерна Декоратор на C#.
Ответ
public interface IStream { void Write(string Данные); }
public class FileStream : IStream { /* ... */ }
public class CompressionDecorator : IStream
{
private readonly IStream _stream;
public CompressionDecorator(IStream stream) => _stream = stream;
public void Write(string Данные) => _stream.Write(Compress(Данные));
}
Вопрос
Как паттерн Декоратор связан с принципом открытости/закрытости?
Ответ
Он позволяет расширять поведение объекта без изменения его исходного кода, что соответствует принципу открытости для расширения и закрытости для модификации.
Вопрос
Что такое паттерн "Фасад" (Facade)?
Ответ
Паттерн Фасад предоставляет унифицированный интерфейс к набору интерфейсов подсистемы, упрощая её использование.
Вопрос
Приведите пример паттерна Фасад.
Ответ
Класс OrderService, который скрывает взаимодействие с подсистемами оплаты, инвентаря и доставки. Клиент вызывает один метод placeOrder(), а фасад координирует все шаги.
Вопрос
Должен ли Фасад содержать бизнес-логику?
Ответ
Нет. Фасад должен только делегировать вызовы подсистемам, не реализуя собственную логику, чтобы не нарушать разделение ответственности.
Вопрос
Что такое паттерн "Приспособленец" (Flyweight)?
Ответ
Паттерн Приспособленец позволяет использовать общие объекты повторно, чтобы сократить потребление памяти при работе с большим количеством мелких объектов.
Вопрос
Какие два типа состояния выделяются в паттерне Приспособленец?
Ответ
Внутреннее состояние — неизменяемые данные, общие для всех контекстов. Внешнее состояние — изменяемые данные, уникальные для каждого использования.
Вопрос
Приведите пример применения паттерна Приспособленец.
Ответ
Отображение миллионов символов в текстовом редакторе: шрифт, размер и цвет (внутреннее состояние) хранятся в общих объектах, а позиция символа (внешнее состояние) передаётся при отрисовке.
Вопрос
Что такое паттерн "Заместитель" (Proxy)?
Ответ
Паттерн Заместитель предоставляет суррогатный объект, который контролирует доступ к другому объекту.
Вопрос
Какие виды заместителей существуют?
Ответ
Удалённый заместитель, виртуальный заместитель, защищающий заместитель и кэширующий заместитель.
Вопрос
Что делает виртуальный заместитель?
Ответ
Он откладывает создание реального объекта до момента первого обращения к нему, что полезно для тяжёлых ресурсов.
Вопрос
Что делает защищающий заместитель?
Ответ
Он контролирует доступ к объекту на основе прав или ролей, проверяя разрешения перед выполнением операций.
Вопрос
Приведите пример кэширующего заместителя.
Ответ
Класс CachedImageLoader, который при первом вызове загружает изображение из сети и сохраняет его, а при последующих возвращает кэш.
Вопрос
Как паттерн Заместитель отличается от Декоратора?
Ответ
Заместитель управляет доступом к объекту и обычно создаётся вместо него, тогда как Декоратор добавляет поведение и требует наличия уже созданного объекта.
Вопрос
Может ли Адаптер быть одновременно Заместителем?
Ответ
Да. Если адаптер также контролирует доступ к адаптируемому объекту (например, кэширует или проверяет права), он сочетает обе роли.
Вопрос
Как паттерн Фасад помогает при тестировании?
Ответ
Он упрощает написание интеграционных тестов, предоставляя точку входа высокого уровня, не требующую знания внутренней структуры подсистемы.
Вопрос
Почему паттерн Компоновщик полезен для GUI-библиотек?
Ответ
Потому что элементы интерфейса (кнопки, панели, окна) образуют иерархию, и единый интерфейс позволяет рекурсивно обрабатывать события или отрисовку.
Вопрос
Как паттерн Мост влияет на количество классов?
Ответ
Он увеличивает количество классов, но снижает степень связывания, делая систему более модульной и гибкой.
Вопрос
Что происходит, если в паттерне Декоратор забыть вызвать базовый метод?
Ответ
Тогда оригинальное поведение будет потеряно, и декоратор превратится в полноценную замену, что нарушает ожидания клиента.
Вопрос
Как паттерн Приспособленец связан с пулом объектов?
Ответ
Приспособленцы часто управляются через пул, где объекты с одинаковым внутренним состоянием переиспользуются вместо создания новых.
Вопрос
Можно ли применять паттерн Фасад внутри одной подсистемы?
Ответ
Да. Фасад может упрощать взаимодействие между слоями одной подсистемы, а не только между подсистемой и внешним миром.
Вопрос
Как паттерн Адаптер помогает при миграции на новую версию API?
Ответ
Он позволяет постепенно заменять вызовы старого API, сохраняя совместимость до полного перехода, без переписывания всего клиентского кода.
Вопрос
Что такое "тонкий" и "толстый" адаптер?
Ответ
Тонкий адаптер только преобразует интерфейс. Толстый адаптер также содержит дополнительную логику, например, кэширование или преобразование данных.
Вопрос
Как паттерн Заместитель реализуется в веб-разработке?
Ответ
Например, через lazy loading изображений: тег <img> изначально показывает заглушку, а реальное изображение подгружается при прокрутке — это виртуальный заместитель.
Вопрос
Почему паттерн Компоновщик требует осторожности при проектировании интерфейса?
Ответ
Потому что методы, смысл которых различен для листьев и узлов (например, addChild()), могут вызывать ошибки, если клиент не проверяет тип.
Вопрос
Как паттерн Декоратор используется в потоках ввода-вывода Java?
Ответ
Классы BufferedInputStream, DataInputStream и другие оборачивают базовые потоки, добавляя буферизацию, парсинг и другие функции.
Вопрос
Что такое "прозрачный" и "безопасный" Компоновщик?
Ответ
Прозрачный Компоновщик объявляет все методы (включая addChild) в общем интерфейсе, обеспечивая единообразие. Безопасный Компоновщик разделяет интерфейсы, предотвращая ошибки вызова addChild у листа.
Вопрос
Как паттерн Мост помогает при работе с разными платформами?
Ответ
Он позволяет отделить логику приложения от платформенно-зависимого кода, так что одна и та же абстракция работает на Windows, macOS и Linux через разные реализации.
Вопрос
Можно ли комбинировать паттерны Декоратор и Заместитель?
Ответ
Да. Например, заместитель может отложить создание объекта, а затем обернуть его в декоратор для добавления логирования или сжатия.
Вопрос
Как паттерн Фасад упрощает работу с микросервисами?
Ответ
API Gateway действует как фасад, агрегируя вызовы нескольких микросервисов в один запрос для клиента.
Вопрос
Что такое "обратный" Адаптер?
Ответ
Это адаптер, который преобразует новый интерфейс к старому, чтобы старый клиентский код мог работать с новой реализацией.
Вопрос
Как паттерн Приспособленец экономит память?
Ответ
Он разделяет общие данные между множеством объектов, храня их в одном экземпляре, а уникальные данные передаются извне.
Вопрос
Почему паттерн Заместитель полезен для удалённых вызовов?
Ответ
Он скрывает сетевую логику, сериализацию и обработку ошибок, предоставляя локальный интерфейс для взаимодействия с удалённым объектом.
Вопрос
Как паттерн Адаптер применяется в ORM?
Ответ
ORM-адаптер преобразует объекты домена в формат, понятный реляционной базе данных, и обратно, выступая как мост между объектной и реляционной моделями.
Вопрос
Можно ли использовать паттерн Компоновщик для обработки команд?
Ответ
Да. Макрокоманда может быть узлом, содержащим список простых команд (листьев), и при выполнении вызывать каждую из них.
Вопрос
Как паттерн Декоратор помогает при логировании?
Ответ
Декоратор может оборачивать сервис и записывать параметры и результаты вызовов, не изменяя сам сервис.
Вопрос
Что делает удалённый заместитель?
Ответ
Он представляет объект, находящийся в другом адресном пространстве (например, на другом сервере), и обрабатывает сетевое взаимодействие.
Вопрос
Как паттерн Фасад отличается от обычного сервисного класса?
Ответ
Фасад специализируется на упрощении сложной подсистемы, тогда как сервисный класс может реализовывать собственную бизнес-логику.
Вопрос
Почему паттерн Мост называется "мостом"?
Ответ
Потому что он соединяет две независимые иерархии — абстракцию и реализацию — как мост между двумя берегами.
Вопрос
Как паттерн Приспособленец применяется в играх?
Ответ
Для отображения тысяч одинаковых деревьев или врагов: модель и текстура хранятся один раз, а позиция и состояние задаются внешними данными.
Вопрос
Можно ли применять паттерн Заместитель для контроля жизненного цикла?
Ответ
Да. Заместитель может управлять созданием и уничтожением реального объекта, например, освобождая ресурсы при отсутствии активных вызовов.
Вопрос
Как паттерн Адаптер помогает при работе с устаревшим кодом?
Ответ
Он позволяет новому коду взаимодействовать со старыми компонентами, не требуя их переписывания.
Вопрос
Что такое "двусторонний" Адаптер?
Ответ
Это адаптер, который позволяет двум несовместимым интерфейсам работать друг с другом в обоих направлениях.
Вопрос
Как паттерн Компоновщик поддерживает рекурсию?
Ответ
Методы узла вызывают те же методы у своих потомков, что позволяет обходить всю иерархию рекурсивно.
Вопрос
Почему паттерн Декоратор часто реализуется через композицию?
Ответ
Потому что композиция позволяет динамически оборачивать объекты в произвольном порядке и количестве во время выполнения.
Вопрос
Как паттерн Фасад способствует слабой связанности?
Ответ
Он изолирует клиентов от изменений внутри подсистемы, так как зависит только от стабильного интерфейса фасада.
Вопрос
Можно ли использовать паттерн Мост для разделения UI и логики?
Ответ
Да. UI-компоненты могут быть абстракцией, а бизнес-логика — реализацией, что упрощает замену одного без влияния на другое.
Вопрос
Как паттерн Приспособленец связан с неизменяемостью?
Ответ
Внутреннее состояние приспособленца обычно неизменяемо, что гарантирует безопасность при совместном использовании.
Вопрос
Что происходит, если в паттерне Заместитель реальный объект недоступен?
Ответ
Заместитель может вернуть заглушку, выбросить исключение или попытаться восстановить соединение, в зависимости от стратегии.
Вопрос
Как паттерн Адаптер применяется в микросервисной архитектуре?
Ответ
Каждый микросервис может предоставлять адаптер для преобразования своего API к стандартному формату, принятому в системе.
Вопрос
Почему паттерн Компоновщик полезен для парсинга выражений?
Ответ
Потому что выражения (например, арифметические) естественным образом образуют дерево: операторы — узлы, числа — листья.
Вопрос
Как паттерн Декоратор используется в валидации?
Ответ
Декоратор может проверять входные данные перед передачей их в основной объект, отклоняя некорректные значения.
Вопрос
Что такое "умный" заместитель?
Ответ
Это заместитель, который добавляет дополнительное поведение, например, подсчёт ссылок, логирование или кэширование.
Вопрос
Как паттерн Фасад помогает при работе с библиотеками?
Ответ
Он скрывает сложность инициализации и настройки библиотеки, предоставляя простой метод типа initialize() или process().
Вопрос
Можно ли применять паттерн Мост к алгоритмам?
Ответ
Да. Алгоритм сортировки может быть абстракцией, а конкретные стратегии (быстрая, слиянием) — реализациями.
Вопрос
Как паттерн Приспособленец влияет на производительность?
Ответ
Он снижает потребление памяти, но может увеличить время на поиск или создание общих объектов, особенно при частых изменениях состояния.
Вопрос
Почему паттерн Заместитель важен для безопасности?
Ответ
Он может проверять права доступа перед выполнением операций, предотвращая несанкционированное использование ресурсов.
Вопрос
Как паттерн Адаптер помогает при интеграции с внешними API?
Ответ
Он нормализует ответы разных API к единому внутреннему формату, упрощая обработку в основном коде.
Вопрос
Что делать, если в паттерне Компоновщик нужно разное поведение для листьев и узлов?
Ответ
Следует использовать безопасный вариант: разделить интерфейсы или применить проверку типа перед вызовом специфичных методов.
Вопрос
Как паттерн Декоратор связан с функциональным программированием?
Ответ
Он аналогичен функции высшего порядка, которая принимает функцию и возвращает новую с расширенным поведением.
Вопрос
Можно ли иметь несколько фасадов для одной подсистемы?
Ответ
Да. Разные фасады могут предоставлять разные уровни детализации или ориентироваться на разные категории клиентов.
Вопрос
Как паттерн Мост помогает при тестировании?
Ответ
Реализацию можно легко заменить на мок, не затрагивая абстракцию, что упрощает изолированное тестирование.
Вопрос
Почему паттерн Приспособленец редко используется явно?
Ответ
Потому что многие его преимущества достигаются автоматически через пулы объектов или неизменяемые структуры данных в современных языках.
Вопрос
Как паттерн Заместитель применяется в ORM?
Ответ
Lazy loading в ORM использует заместитель: при первом обращении к свойству сущности загружается реальные данные из базы.
Поведенческие паттерны
Вопрос
Что решают поведенческие паттерны проектирования?
Ответ
Поведенческие паттерны определяют способы взаимодействия объектов и распределения обязанностей между ними, обеспечивая гибкость в управлении потоком выполнения и связями.
Вопрос
Какие основные поведенческие паттерны описаны в книге GoF?
Ответ
Основные поведенческие паттерны: Цепочка обязанностей, Команда, Интерпретатор, Итератор, Посредник, Хранитель, Наблюдатель, Состояние, Стратегия, Шаблонный метод и Посетитель.
Вопрос
Что такое паттерн "Цепочка обязанностей" (Chain of Responsibility)?
Ответ
Паттерн Цепочка обязанностей передаёт запрос последовательно по цепочке обработчиков, пока один из них не обработает его.
Вопрос
Приведите пример применения паттерна Цепочка обязанностей.
Ответ
Обработка HTTP-запросов в middleware: логирование, аутентификация, валидация — каждый этап может завершить обработку или передать запрос дальше.
Вопрос
Как паттерн Цепочка обязанностей поддерживает слабую связанность?
Ответ
Отправитель запроса не знает, какой обработчик его выполнит, и зависит только от абстрактного интерфейса обработчика.
Вопрос
Что такое паттерн "Команда" (Command)?
Ответ
Паттерн Команда инкапсулирует запрос как объект, позволяя параметризовать клиентов с различными запросами, ставить их в очередь, логировать и поддерживать отмену операций.
Вопрос
Приведите пример реализации паттерна Команда на Java.
Ответ
interface Command {
void execute();
}
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) { this.light = light; }
public void execute() { light.turnOn(); }
}
class RemoteControl {
public void pressButton(Command command) {
command.execute();
}
}
Вопрос
Как паттерн Команда позволяет реализовать отмену действия?
Ответ
Каждая команда может хранить состояние до выполнения и предоставлять метод undo(), восстанавливающий предыдущее состояние.
Вопрос
Что такое паттерн "Интерпретатор" (Interpreter)?
Ответ
Паттерн Интерпретатор определяет грамматику языка и интерпретатор для выражений на этом языке, представляя каждое правило грамматики в виде класса.
Вопрос
В каких случаях применяется паттерн Интерпретатор?
Ответ
Он применяется при реализации простых языков, регулярных выражений, DSL (предметно-ориентированных языков) или правил бизнес-логики.
Вопрос
Почему паттерн Интерпретатор редко используется в крупных системах?
Ответ
Потому что он плохо масштабируется при усложнении грамматики и требует значительных усилий для оптимизации производительности.
Вопрос
Что такое паттерн "Итератор" (Iterator)?
Ответ
Паттерн Итератор предоставляет способ последовательного доступа ко всем элементам составного объекта без раскрытия его внутреннего представления.
Вопрос
Приведите пример использования паттерна Итератор в Python.
Ответ
class Collection:
def __init__(self, items):
self._items = items
def __iter__(self):
return iter(self._items)
# Использование:
for item in Collection([1, 2, 3]):
print(item)
Метод __iter__ делает объект итерируемым.
Вопрос
Как паттерн Итератор упрощает добавление новых способов обхода?
Ответ
Можно создать несколько итераторов для одного коллекционного класса, каждый со своей логикой обхода (например, прямой, обратный, фильтрованный).
Вопрос
Что такое паттерн "Посредник" (Mediator)?
Ответ
Паттерн Посредник инкапсулирует взаимодействие между множеством объектов, заставляя их общаться не напрямую, а через посредника.
Вопрос
Приведите пример применения паттерна Посредник.
Ответ
Чат-комната: пользователи отправляют сообщения не друг другу, а комнате, которая рассылает их всем участникам.
Вопрос
Как паттерн Посредник снижает связанность компонентов?
Ответ
Компоненты зависят только от посредника, а не от всех других компонентов, что упрощает их повторное использование и модификацию.
Вопрос
Что такое паттерн "Хранитель" (Memento)?
Ответ
Паттерн Хранитель сохраняет внутреннее состояние объекта без нарушения инкапсуляции, чтобы позже восстановить его.
Вопрос
Какие три участника выделяются в паттерне Хранитель?
Ответ
Источник (Originator) — объект, чьё состояние сохраняется. Хранитель (Memento) — объект, содержащий состояние. Опекун (Caretaker) — управляет сохранёнными состояниями.
Вопрос
Приведите пример использования паттерна Хранитель.
Ответ
Функция "Отменить" в текстовом редакторе: каждое изменение сохраняется как мементо, и при отмене восстанавливается предыдущее состояние документа.
Вопрос
Что такое паттерн "Наблюдатель" (Observer)?
Ответ
Паттерн Наблюдатель определяет зависимость "один ко многим" между объектами, так что при изменении состояния одного объекта все зависящие от него автоматически уведомляются.
Вопрос
Приведите пример реализации паттерна Наблюдатель на C#.
Ответ
public class Subject
{
private List<Action> _observers = new();
public void Subscribe(Action observer) => _observers.Add(observer);
public void Notify() { foreach (var o in _observers) o(); }
}
// Использование:
var subject = new Subject();
subject.Subscribe(() => Console.WriteLine("Обновление!"));
subject.Notify();
Вопрос
Как паттерн Наблюдатель применяется в реактивном программировании?
Ответ
Он лежит в основе потоков данных: подписчики получают уведомления о новых значениях, ошибках или завершении потока.
Вопрос
Что такое паттерн "Состояние" (State)?
Ответ
Паттерн Состояние позволяет объекту изменять своё поведение в зависимости от внутреннего состояния, создавая впечатление изменения класса объекта.
Вопрос
Приведите пример применения паттерна Состояние.
Ответ
Автомат продаж: поведение при нажатии кнопки "Купить" зависит от состояния — "ожидание монет", "выбор товара", "выдача товара".
Вопрос
Как паттерн Состояние отличается от условных операторов?
Ответ
Он заменяет сложные условные конструкции на полиморфизм, делегируя поведение конкретному объекту-состоянию.
Вопрос
Что такое паттерн "Стратегия" (Strategy)?
Ответ
Паттерн Стратегия определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми.
Вопрос
Приведите пример паттерна Стратегия на Python.
Ответ
class SortStrategy:
def sort(self, Данные): pass
class QuickSort(SortStrategy):
def sort(self, Данные): return sorted(Данные)
class BubbleSort(SortStrategy):
def sort(self, Данные):
# реализация пузырьковой сортировки
return Данные
class Context:
def __init__(self, strategy):
self._strategy = strategy
def execute_sort(self, Данные):
return self._strategy.sort(Данные)
Вопрос
Как паттерн Стратегия поддерживает принцип открытости/закрытости?
Ответ
Новые алгоритмы можно добавлять как новые стратегии без изменения контекста или существующих стратегий.
Вопрос
Что такое паттерн "Шаблонный метод" (Template Method)?
Ответ
Паттерн Шаблонный метод определяет скелет алгоритма в базовом классе, делегируя некоторые шаги подклассам.
Вопрос
Приведите пример паттерна Шаблонный метод на Java.
Ответ
abstract class DataProcessor {
public final void process() {
loadData();
processData();
saveData();
}
abstract void loadData();
abstract void processData();
void saveData() { /* реализация по умолчанию */ }
}
Вопрос
Почему метод шаблона часто объявляется как final?
Ответ
Чтобы запретить подклассам изменять общий порядок шагов алгоритма, обеспечивая целостность процесса.
Вопрос
Что такое паттерн "Посетитель" (Visitor)?
Ответ
Паттерн Посетитель позволяет добавлять новые операции к объектам структуры, не изменяя их классы, путём вынесения операций в отдельный класс-посетитель.
Вопрос
Приведите пример применения паттерна Посетитель.
Ответ
Генерация отчётов для разных типов элементов UI: кнопка, поле ввода, метка — каждый принимает посетителя, который формирует HTML, JSON или PDF.
Вопрос
Как паттерн Посетитель связан с двойной диспетчеризацией?
Ответ
Он эмулирует двойную диспетчеризацию: первый вызов определяет тип посетителя, второй — тип элемента, что позволяет выбрать нужную комбинацию.
Вопрос
Почему паттерн Посетитель усложняет добавление новых элементов?
Ответ
Потому что каждый новый элемент требует добавления метода accept() и обновления всех существующих посетителей.
Вопрос
Как паттерн Цепочка обязанностей отличается от Посредника?
Ответ
Цепочка передаёт запрос линейно до первого обработчика, тогда как Посредник координирует взаимодействие всех участников одновременно.
Вопрос
Можно ли комбинировать паттерны Наблюдатель и Команда?
Ответ
Да. Наблюдатель может передавать команды в качестве уведомлений, что позволяет отменять или повторять действия.
Вопрос
Как паттерн Стратегия используется в алгоритмах сортировки?
Ответ
Разные стратегии реализуют разные алгоритмы (быстрая, слиянием, пузырьковая), и выбор осуществляется динамически в зависимости от данных.
Вопрос
Что делает паттерн Итератор удобным для клиентского кода?
Ответ
Он предоставляет единый интерфейс для обхода различных структур данных — списков, деревьев, графов — без знания их внутреннего устройства.
Вопрос
Как паттерн Хранитель обеспечивает инкапсуляцию?
Ответ
Мементо может быть неизменяемым и предоставлять данные только источнику, не позволяя опекуну или другим объектам их изменять.
Вопрос
Почему паттерн Интерпретатор часто заменяется парсерами?
Ответ
Потому что готовые парсер-генераторы (например, ANTLR) эффективнее и надёжнее для сложных грамматик.
Вопрос
Как паттерн Состояние помогает избежать "спагетти-кода"?
Ответ
Он локализует поведение, специфичное для каждого состояния, в отдельных классах, устраняя глобальные условные конструкции.
Вопрос
Что происходит, если в паттерне Наблюдатель наблюдатель не отписывается?
Ответ
Это приводит к утечке памяти, так как источник удерживает ссылку на наблюдателя, предотвращая его сборку мусором.