Всем привет! Меня зовут Роман Сакутин и сейчас я хочу привести 3 примера использования паттернов GoF при разработке компьютерных игр с Unity и CSharp
Дальше вы увидите примеры связанные со следующими шаблонами:
— Visitor (Визитёр)
— Observer (Наблюдатель)
— Decorator (Декоратор)
Visitor
Визитёр — это паттерн который описывает операцию над объектами другого типа. При этому, мы выносим эту операцию из ответственности того, кто эту операцию совершает. Классический пример: у нас есть некая иерархия типов и есть ряд объектов, который имеют различный тип из этой иерархии. Нам нужно выполнить разные действия, для каждого объекта, в зависимости от его типа. Тогда нам нужно либо использовать большой свитч с выбором действия в зависимости от типа, либо воспользоваться этим паттерном.
Пример из жизни:
Есть система который производит выстрел в сцене, и возвращает некую абстракцию Hit. Фактически, там скрывается конкретный тип попадания, либо по цели, либо по окружению.
Попадания представляются такой вот иеерархией
После выстрела, нам нужно сделать разные действия для разных типов попадания. Тогда мы можем сделать это так:
Аналогом будет воспользоваться паттерном визитёр. Сначала нам нужно будет изменить сам тип Hit, сделав уточнение что над ним может совершаться некая операция.
Интерфейс же визитёра выглядит следующим образом.
Благодаря перегрузки, определения какой метод вызвать происходит без нашего участия. Далее мы можем создать класс реализующий этот интерфейс. Например, это может быть класс, который по разному засчитывает попадания. Так попадания по окружению будет считаться за промах, а по цели за чистое попадание.
Могут быть ещё классы, например отвечающие за визуализацию.
Работа с этим делом невероятно простая.
После получения попадания, мы говорим какого класса операцию хотим совершить, и будет выбрана та, которая подходит под тип выстрела.
Преимущества использования этого паттерна в следующем:
При расширение иерархии выстрелов, мы можем добавить новый метод в интерфейс визитёра и с помощью появишихся ошибок, мы найдём места, где не хватает этих методов. Т.е те точки где не хватает операций под новый тип. В случае с ифом, при добавление нового типа попадания, нам бы пришлось в ручную искать все точки обработки и постараться ни одну не пропустить.
Observer
Классическая модель взаимодействия — pull. Она заключается в том, что мы сами просим какие-то данные, и работаем с ними. Так при разработке компонента который рисует здоровье пользователя, мы можем каждый кадр в ручную вытягивать текущее значения здоровья и обновлять интерфейс.
В замен мы можем воспользоваться push моделью. Когда игрок сам будет сообщать об изменение здоровья и тем изменять визуальный компонент. Паттерн Ovserver как раз-таки позволяет это сделать, но с большим преимуществом — он позволяет избавиться от зацепки кода. Когда класс игрока знает об всех, кому нужны данные и неразрывно с ними связан.
Реализации обсервера в C# «встроена» с помощью синтаксиса событий. Выглядеть это всё может примерно следующим образом:
Decorator
Декоратор позволяет изменить поведение объекта не меняя его интерфейс. Это композиционное решение задачи переопределения поведения базового типа.
Например у нас есть некий тип который описывает характеристики пользователь Stats. И у нас стоит задача, изменять их под гнётом пассивного заклинания. В таком случае мы можем задекарировать объект с характеристиками. Декоратор нам также позволит убирать и добавлять этот эффект когда мы захотим, без лишних ифов.
В данном примере, пассивный эффект усиляет все характеристики игрока в два раза.
Подытожим
Мы вкратце рассмотрели три паттерна и поверьте их гораздо больше (только GoF 23 штуки) и каждый из них можно рассмотреть глубже и через призму других задач.
Надеюсь вам понравилось!