Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > Dukobpa3

Рейтинг: 5.00. Голосов: 2.

Инкапсуляция объекта vs инкапсуляция поведения

Запись от Dukobpa3 размещена 14.11.2013 в 22:12
Обновил(-а) Dukobpa3 18.11.2013 в 22:33

Рассмотрим два подхода к программированию.
Использование полноценных логических объектов которые что-то могут.
И использование разного рода статических функций и классов для обработки объектов.

Итак. ООП нас учит таким правилам как инкапсуляция и наследование.
Инкапсуляция это типа как объединить некий срез логики в одном месте, в одном классе (на пару уровней выше можно уже рассматривать инкапсуляцию на уровне модулей, к примеру, но сейчас пока не об этом). Наследование это к примеру мы уже сделали некий инкапсулированный объект - табуретка. Хотим написать стул. Стул - это табуретка со спинкой. Соответственно берем, наследуемся стулом от табуретки. И автоматически наш стул уже умеет всё то что умела табуретка, и имеет все свойства которые имела табуретка. Добавляем в нее спинку и методы, которые со спинкой связаны - вуаля. Написали пять строчек и стул готов. А всё благодаря к тому что мы уже раньше постарались и написали табуретку.

Так вот наследование это конечно круто, если не пытаться смешивать роды и виды с подвидами. Иногда бывает очень сложно классифицировать эти все семейства разнородных сущностей. Только тема не об этом.

А тема вот о чем.
Вот к примеру есть у нас табуретка.
У нее есть свойства:
- 4 ножки.
- Восседалище.

С ней можно что-то делать (методы):
- сидеть на ней
- двигать
- кидать
- ломать
- прочее

А еще у нас есть тумбочка.
У нее тоже есть свойства:
- 4 ножки
- вместилище
- дверки

С ней можно что-то делать (методы):
- положить в нее что-то
- двигать ее
- кидать
- ломать

//****************************************
Так собственно вот.
Что мы можем с этим всем сделать.
Вариантов у нас на самом деле два, а не один, как может сразу показаться.
Первый. Очевидный - сделать базовый класс "мебель", с примерно следующим составом:
Свойства
- ножки
- размер
- вес

Методы
- двигать
- кидать
- ломать

Далее этот базовый класс расширяем табуреткой и тумбочкой. Соответственно в табуретке дописывается восседалище, а в тумбочке вместилище и вуаля.

Но мы ведь можем пойти и другим путем.
Например у нас есть изометрическая карта. На ней есть стопицот всего. Например это таки комната. В ней может быть мебель, могут быть НПЦ, могут быть враги, друзья, мусор и прочая муть.
И например нам это всё надо уметь перемещать.
В таком случае касательно тумбочки и табуретки мы можем убрать методы перемещения. Написать статик класс "перемещатор", с методом:
переместить(объект, координаты).
И пользоваться этим методом для ВСЕХ объектов, которые мы можем перемещать по этой карте. Таким образом мы инкапсулировали ПОВЕДЕНИЕ в отдельный класс и отдельный метод. Функционал перемещения то один и тот же. Объект был на клетке такой-то, переехал в клетку такую-то. Зачем это всё писать в каждом отдельном классе, или же придумывать какую-то нереальную цепочку наследования мусора и табуретки от одной сущности?

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

Со статиками появляются дополнительные задачи, например какие-то интерфейсы по типу ИПеремещабельный, ИРазрушабельный. Но это конкретно темы не касается, потому останавливаться не буду.

//****************************************
Это собственно сама суть.
Первый подход с наследованием и полноценными объектами можно назвать инкапсуляцией объекта, второй со статиками - можно назвать инкапсуляцией поведения (термины не научные и не технические, но я это называю так, так что если к терминологии будут вопросы я готов выслушать и че-то подкорректировать).

//****************************************
Теперь плюсы и минусы подхода.

Вариант с наследованием хорош когда у вас есть четкое дерево наследования, желательно не больше трех последовательных наследований. И к тому же если это оправдано.
Например цепочка мебели. У нас есть класс мебели, от которого все наследуются, и там может где-то еще стул от табуретки а шкаф от тумбочки. Но не более. Если наше дерево распускает ветви на пять уровней в глубину - лучше придумать что-то другое. Да и например есть у вас диван. Вы его откуда отнаследуете? от кресла(мягкое, с быльцами и спинкой, но короткое) или от лавочки в парке(Длинное, с быльцами, спинкой, но не мягкое)?

Второй вариант с делегированием поведения хорош когда вам побоку что двигать. У вас есть разнородный перемещабельный хлам. Вот вы его и перемещаете. А мебель это, или мусор, или камни, или стены - вам пофиг. Объект имплементит перемещабельный интерфейс и вуаля. В одном месте написан метод перемещения и всем хорошо. Но это становится плохо, когда визуально перепмещение отличается у стула и у мусора например. Стул просто передвигается, мусор перекатывается. Уже надо думать где что использовать.

//****************************************
Соответственно использование статиков это как раз про второй вариант. Если у вас есть возможность инкапсулировать какое-то поведение - вы его выносите в статик класс.

Так же, например, с той жк изометрической картой вам часто надо считать координаты и переводить пиксели в изометрические х-у. В таком случае опять же выносим метод подсчета координат в в статик метод в какие-то IsoUtils.
Или у вас есть желание разрушать объекты, но не охота писать в каждом классе дестроеры, как это принято в плюсах. Опять же можно написать какой-то универсальный метод для этих целей, и больше не заморачиваться.

//****************************************
В статиках нет ничего плохого либо хорошего. Это как еще одна отвертка в вашем наборе инструментов. Главное знать где его правильно использовать
Ну и как верно заметил в комментариях товарищ ChuwY - такого же эффекта инкапсуляции поведения можно добиться еще многими методами кроме статиков. Статик это самый простой в использовании вариант. Но не стоит им злоупотреблять. Как и любой другой инструмент нужно использовать к месту.
Идеальный вариант для стстика это классы по типу Math, в которых ничего не сохраняется, функция отработала, выдала результат и больше о ней не вспоминаем. Если же функция в процессе что-то куда-то сохраняет - при неправильной организации вполне можно ожидать утечек памяти или иных неприятных последсвий.

Как-то так. Искренне ваш.
Всего комментариев 11

Комментарии

Старый 15.11.2013 09:40 Korchy вне форума
Korchy
 
Аватар для Korchy
Жаль, что в AS нет множественного наследования Проблемы наследования дивана от лавочки или кресла не возникало бы в принципе.
Старый 15.11.2013 09:52 gloomyBrain вне форума
gloomyBrain
 
Аватар для gloomyBrain
Мне кажется что автор описал паттерн Entity Systems. Который, кстати, вполне себе может заменить множественное наследование (в контексте нескольких поведнеий у одного объекта)
Старый 15.11.2013 12:04 olexandr вне форума
olexandr
 
Аватар для olexandr
по поводу entity есть отличная статья на хабре, но большая )
Старый 15.11.2013 13:47 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
Цитата:
описал паттерн Entity Systems
Нет, я пытался просто описать ситуацию, в которой статик это хорошо. Видимо не очень получилось
Entity system это не совсем паттерн, это больше подход опять же.
И там юзается по больше части не статик, а композиция из микроповедений.
Добавил пару примеров, мб понятнее будет.

Цитата:
Жаль, что в AS нет множественного наследования
Я думаю от множественного наследования больше проблем, чем профита.
Скрестил собаку с птичкой, родил генетического урода, не способного к жизни, и молодец.
Обновил(-а) Dukobpa3 15.11.2013 в 14:22
Старый 18.11.2013 19:13 ChuwY вне форума
ChuwY
 
Аватар для ChuwY
Все хорошо.
Только инкапсулировать поведение можно не только в статике
Старый 18.11.2013 19:25 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
Есть например чудесный паттерн стратегия.
И еще много всяких энтити систем.
Но статья была о статиках Может с названием прогадал
Старый 03.12.2013 12:21 murz вне форума
murz
вы с этими статиками огребете когда логика начнет менятся и вашей тумбочке при перемещение надо будет к примеру "пернуть".
иначнется
Код AS3:
if(obj is tumbocka){
}
Старый 03.12.2013 15:01 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
С любым подходом можно огрести.
Старый 11.12.2013 09:33 DCH вне форума
DCH
 
Аватар для DCH
На самом деле, скорее всего начнется такое:
Код AS3:
public class Blah implements IMovable
{
    public function move():Boolean
    {
         this.fart();
         return true;
    }
}
 
....
public static function movieMovables(value:IMovable):void
{
    if(!value.move())
    {
         value.x=blah;
    }
}
Ничего сверхотвратительного в этом подходе не видно, не радует лишь сама идея декомпозиции кода, изначально заложенная в данном шаблоне.

Цитата:
по поводу entity есть отличная статья на хабре, но большая )
Цитата:
Архитектура систем сущностей пришла из попытки решить проблемы игрового цикла. Она делает игровой цикл ядром игры и предполагает, что упрощение игрового цикла важнее, чем все остальное в архитектуре современной игры. Это важнее, чем отделить вид от контролера, к примеру.
Это, едритская сила, не важнее. Это решает совершенно другую задачу.
Обновил(-а) DCH 11.12.2013 в 09:54
Старый 11.12.2013 13:11 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
Цитата:
На самом деле, скорее всего начнется такое:
Вполне возможно и начнется, если пользоваться этим неправильно.

Я такой подход использую в основном там где:
- гарантировано обрабатываемые объекты будут обрабатываться одинаково, тут будет одна общая функция, например как в твинерах часто делают.
- либо же результат обработки должен быть идентичным, тут например какой-то Destroyer.destroy(obj); - тут уже внутри будет какой-то набор условий, в зависимости от того что же именно мы дестроим, но плохого в этом ничего нет. Мы просто получим какой-то универсальный разрушатель объектов, и дальше по коду мы не будем думать как это разрушение работает, потому что все объекты будут разрушаться одинаково.

И иногда люблю делать статик просто чтоб мой основной большой класс был меньше.
Тут уже никакой универсальности. Просто есть класс-объект. И плюс к нему есть несколько классов-обработчиков. Класс-объект получается маленьким и худеньким, и в обработчиках уже какое-то поведение этого класса-объекта.
Многие тут используют команды, в том числе и я. Тут уже где что удобнее.
Старый 11.12.2013 13:22 DCH вне форума
DCH
 
Аватар для DCH
Цитата:
Вполне возможно и начнется, если пользоваться этим неправильно.
Я совершенно этого не оспариваю, наоборот, это был ответ на это, простите за тавтологию:
Цитата:
вы с этими статиками огребете когда логика начнет менятся и вашей тумбочке при перемещение надо будет к примеру "пернуть".
иначнется
Я лишь показал, что и пернуть вполне возможно, практически без костылей. Но грозит декомпозицией и неоднозначностями, что усложнит поддержку кода, не более и не менее. В методе перемещаемого объекта легко описываются специфические для его перемещения действия. В зависимости от того, требуется ли еще и внешняя дополнительная общая обработка - возвращается булева. Все нормально поддается детализации, если головой немного подумать.
 

 


Часовой пояс GMT +4, время: 19:38.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2022, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.