Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > Обсуждение шаблонов проектирования (стереотипы) |
Автор: atomicxp 12.6.2009, 17:57 | ||||||||||
Как известно для проектирования ООП систем разумно использовать шаблоны проектирования. Существует ряд правил, одно из которых было описано в книге "Совершенный код", например, группировать не более семи элементов в одной сущности (классе). Однако, помимо общих правил, есть разнообразные модели создания объектов. По сути это важно во всех языках использующих ООП, но меня это больше волнует по части C++ и применительно к кроссплатформенным библиотекам, таким как STL, Boost, GTK+, Qt SDK, WxWidgets и многих других. По сути во всех этих библиотеках редко соблюдают правила и менее часто соблюдают шаблоны проектирования. Впрочем это не так важно, главное у меня появилась идея обсудить шаблоны проектирования классов/объектов. Пока думаю можно рассмотреть вот эти: * 1 Структурные паттерны проектирования классов/обьектов o 1.1 Адаптер (Adapter) - GoF o 1.2 Декоратор (Decorator) или Оболочка (Wrapper) - GoF o 1.3 Заместитель (Proxy) или Суррогат (Surrogate) - GoF o 1.4 Информационный эксперт (Information Expert)- GRASP o 1.5 Компоновщик (Composite) - GoF o 1.6 Мост (Bridge), Handle (описатель) или Тело (Body) - GoF o 1.7 Низкая связанность (Low Coupling) - GRASP o 1.8 Приспособленец (Flyweight) - GoF o 1.9 Устойчивый к изменениям (Protected Variations) - GRASP o 1.10 Фасад (Facade) - GoF * 2 Паттерны проектирования поведения классов/обьектов o 2.1 Интерпретатор (Interpreter ) - GoF o 2.2 Итератор (Iterator) или Курсор (Cursor) - GoF o 2.3 Команда (Command), Действие (Action) или Транзакция (Транзакция) - GoF o 2.4 Наблюдатель (Observer), Опубликовать - подписаться (Publish - Subscribe) или Delegation Event Model - GoF o 2.5 Не разговаривайте с неизвестными (Don't talk to strangers) - GRASP o 2.6 Посетитель (Visitor) - GoF o 2.7 Посредник (Mediator) - GoF o 2.8 Состояние (State) - GoF o 2.9 Стратегия (Strategy) - GoF o 2.10 Хранитель (Memento) - GoF o 2.11 Цепочка обязанностей (Chain of Responsibility) - GoF o 2.12 Шаблонный метод (Template Method) - GoF o 2.13 Высокое зацепление (High Cohesion) - GRASP o 2.14 Контроллер (Controller) - GRASP o 2.15 Полиморфизм (Polymorphism) - GRASP o 2.16 Искусственный (Pure Fabrication) - GRASP o 2.17 Перенаправление (Indirection) - GRASP * 3 Порождающие паттерны проектирования o 3.1 Абстрактная фабрика (Abstract Factory, Factory), др. название Инструментарий (Kit) - GoF o 3.2 Одиночка (Singleton) - GoF o 3.3 Прототип (Prototype) - GoF o 3.4 Создатель экземпляров класса (Creator) - GRASP o 3.5 Строитель (Builder) - GoF o 3.6 (Фабричный метод) Factory Method или Виртуальный конструктор (Virtual Constructor) - GoF Ну и другие по мере появления. Первый шаблон проектирования для рассмотрения "Интерфейс" (категория: Основные шаблоны (Fundamental)). Следует так же отметить, что открытую часть класса так же называют интерфейсом, но речь пойдёт не о ней. В нашем случае интерфейс может иметь как открытые члены, плюс некие комбинации, такие как защищённые. Интерфейс не содержит данные, его методы имеют полиморфную природу.
virtual указывает на возможность полиморфизма, а = 0 о том что метод имеет чисто абстрактную природу. Однако в вики видим следующую картину.
Наследование проходит как public, но помимо этого существует статическая функция возвращающая указатель на класс созданный по шаблону проектирования интерфейса. Лично мне это кажется странным, зачем создавать класс A внутри интерфейса. Полиморфизм через интерфейс может достигаться за счёт приведения типов, смысла плодить лишние методы нет. К тому же это нарушает чистую абстракцию которой по идее должен следовать класс созданный по шаблону проектирования интерфейса. Добавлено @ 18:11 Простейший случай использования, который вероятно нужно усовершенствовать:
Вывод:
|
Автор: atomicxp 12.6.2009, 22:17 | ||||||||||||
Это http://ru.wikipedia.org/wiki/Interface_(%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD).
На другом форуме человек пришёл к такому же выводу. Абстрактные фабрики рассмотрим позже. Вот урезаное продолжение. ################################ Ну что ж, проблема виртуальных деструкторов рассмотрена. Конечно, данная концепция сильно отличается от C#, хотя при правильном использовании шаблоны проектирования сохраняют своё предназначение, и классам можно смело присваивать стереотип - Interface. Так же следует отметить, что компилятор подсказывает о том, что нужно записать виртуальный деструктор.
Были протестированные различные варианты, где при помощи оператора delete вначале удалялся интерфейс, в другом случае класс использующий интерфейс, менялось использование методов, через класс и через интерфейс, и кое-какие другие тесты. Конечный вариант может выглядеть как-то так, хотя здесь нужны изменения.
Вывод:
В итоге виртуальный деструктор нужен, если кому-то придёт в голову удалить исходный объект через интерфейс. Хотя такое лучше не делать из-за множественного наследования и в следствии этого потери основного предназначение интерфейса. Вопрос о квалификаторах доступа пока откладываю на потом в силу того, что для них нужны более совершенные примеры, а нужно ещё рассмотреть множество шаблонов проектирования и их использование применительно к C++ и кроссплатформенному программированию. ################################
В этом и вся суть обсуждения. Пока человек думает об интерфейсе как о паттерне, может даже записать его на UML в графическом виде, он как бы ничего не имеет, кода то нет. Эта тема и посвящена совмещению проектирования и реализации. Планирую в ходе дискуссий выявить наиболее оптимальные способы этого применительно к C++. Есть ещё идея исключить из программирования смешанные классы и пользоваться лишь чистыми паттернами (шаблонами) проектирования. |
Автор: math64 12.6.2009, 23:56 | ||
Да не получится. Иногда воместно исполбзуются несколько паттернов, иногда паттерн используется вместе с обычным кодом, иногда в голом паттерне нет никагого смысла. В C# и Java паттерн interface встроен в язык, а в C++ нет. В принципе, class - тоже паттерн, встроенный в эти языки, но не встроенный в "C", где его однако тоже можно использован (см. исходники ядра Linux). for, while и if тоже паттерны, встроенные в языки высокого уровня, но не встроенные в язык ассемблера. |
Автор: atomicxp 13.6.2009, 00:16 |
Думаю надо детально рассмотреть остальные шаблоны проектирования. Не знаю как другие программисты, но вот что касается интерфейсов, то их я бы никогда не стал смешивать с другими шаблонами проектирования. Если смесь по каким-либо причинам всё таки необходима, это тоже нужно отметить. Добавлено через 6 минут и 14 секунд P.S. В этой теме обсуждаются как и заявлено - шаблоны проектирования классов/объектов и реализации только для языка C++. |
Автор: mes 13.6.2009, 00:25 | ||||||||||
![]()
ни класс, ни интерфейс не удаляются посредством оператора delete. Эта операция в Cpp применима только к объектам ![]()
Множественное наследование не мешает полиморфному удалению объекта и как следствие нет никакой "потери предназначения".
Только вот автор темы все время пытается подменить понятия. Его высказывания несут слишком утвердительный характер, а при этом, мягко сказать, мало достоверны, что плохо отражается на обсуждении ![]() Добавлено через 6 минут и 11 секунд
Смотря что подразумевать под выражением "смешивать патерны". Если Вы думаете что каждый паттерн должен быть описан своим и только своим классом - Вы сильно ошибаетесь. |
Автор: atomicxp 13.6.2009, 00:49 | ||||
Не считаю нужным разжёвывать всё как для маленьких. Понятное дело объект, который называется так же образцом (экземпляром) класса, и создаётся при операции инстанцирования (instantiation). Я не претендую на высокоточное объяснение каждой детали, кому надо, тот поймёт, другие пусть читают книжки прошедшие многократную редакцию. Новичкам которые не понимают очевидных вещей, хоть и полезно почитать эту тему, но вряд ли они многое из неё вынесут. Придирщикам же мне сказать нечего.
Лучшим вариантом если что-то не нравится было бы написать код. Не устраивает реализация интерфейса, напиши как ты его видишь в C++. |
Автор: mes 13.6.2009, 01:03 |
Понятно. Если к моим постам отношение как придиркам, спасибо за компанию. Пока. |
Автор: DrHex 13.6.2009, 03:09 | ||
Природа интерфейса висьма смутна в цпп. 1)Интрефейс подобен абстрактному классу. 2)Интерфейс не имеет реализации, но диктует сигнатуру класса Интерфейс не имеет реализации, но диктует сигнатуру класса - Конструктор и деструктор у интерфейса должен быть в любом случае, пусть дажет и не декларированый. Первой что хочется сделать это виртуальный деструктор, для того что бы можно было удалить объект через указатель базового класса, но это уже будет прямая декларация с вытикающей реализацией. Мелкомягкие обошли это в COM объектах, ввели метод release в интерфейсе IUnknown(но деструктор то остается(конструктор тоже)). Так что интерфейс не совсем естественное чудо природы, лучше применять абстрактные классы(хотя для многих эти понятия игра слов....) Применять поттерны проектирование хорошо для для высоко уровней абстракции. К примеру Имеется поля класса, которое для всех объектов сущетсвует в едином классе, тип данных к примеру int, но писать для него оболочку то и есть класс как то не совсем разумно(то и есть singletone), проще сделать его статическим. но вот если это поля не должно сущетсвовать без объекта то здесь уже и оболочка хотя и сново таки для int учень транжирно(не говорить о производительности, можно учесть хотя бы то время которое программист на это затратит), а вот если это объект серъездный(много памяти отводится) то синглтон переходит в рефернс коунт(почемуто его редко описывают, а вот паттерн действительно хороший). Так и к тому же, при интенсивном использование паттернов проектирования, очень сильно в падает производительность. К примеру MFC отказали от сильной виртуализации, так как событий для объектов(то и есть контролов, окон) уж очень много, и пара сотен виртуальных функций не очень хорошо на производительность скажутся(оно построение объекта как возрастет, не говоря уже про память 4 байта на каждую функцию, а то и восемь для 64 битов) В частноти для замены динамического палиформизма существуют шаблоны(разумеется что эти вещи совсем имеют разный характер, не которых случаях могут заменять друг друга, ну а иногда дополняют).
При всем уважении, к указателям на объект. Паттерны проектирование создавались с той целью, что бы моно было взять готовый "велосипед", точнее алоритм, но стого придерживатся ко всем правилам, это терять свое время по напрастну(если программить так за время, то терять денеги компанни, что преведет вашего начальника к не очень хорошому настроению). Автор данного поста решил написать статью про паттрены(в перспективе книгу)? |
Автор: mes 13.6.2009, 03:28 | ||||
Хотя оператор и принимает указатель на объект, но операция (удаления) производится над объектом, а не над указателем ![]() Добавлено через 4 минуты и 59 секунд
нда... ![]() |
Автор: atomicxp 13.6.2009, 04:24 | ||||||
При использовании шаблонов проектирования по типу интерфейса говорят производительность может упасть.
Лично я не проверял, поверю им на слово. Скорее всего это действительно наступит только если создавать таким образом свой фреймворк. И тем не менее считаю это не столь важным, иначе бы пришлось задуматься об отказе использования виртуальных функций. Опять же о памяти пекутся, но какая собственно разница, не килобайтами её считаем.
Просто упорядочиваю знания. Насчёт синглтона, а так же как майкрософт "ускоряет" свои продукты напишу чуть позже. |
Автор: Курсант 13.6.2009, 05:13 |
![]() Вот от этого точно можно испугаться... * Ушел повторять две тысячи раз мантру "Копай глубже кидай дальше отдыхай пока летит" * |
Автор: Lazin 13.6.2009, 10:09 | ||||||||||
ты из какого леса? ![]()
итак, у класса нет сигнатуры, у класса есть(ты не поверишь) - интерфейс, интерфейс != абстрактный класс
Виртуализаия, это несколько иное. Если класс содержит хоть одну вирт ф-ю, то его размер увеличивается на размер указателя на таблицу вирт. ф-ий, на каждую ф-ю дополнительная память не выделяется. Вызов вирт. ф-ии немного тяжелее чем вызов обычной, вот и все. Добавлено через 1 минуту и 7 секунд
а разве интерфейс, это паттерн проектирования? |
Автор: mes 13.6.2009, 10:26 |
![]() |
Автор: math64 13.6.2009, 11:36 | ||
Если вы хотите запретить удалять объект через интерфейс, объявите деструктор в секции protected:
|
Автор: atomicxp 13.6.2009, 12:45 | ||||||
Очень хороший совет:
И ещё я подумал, может стоит сделать виртуальный деструктор чисто абстрактным. Все равно ведь не используется в силу определения интерфейса. Над этим стоит поразмышлять. Добавлено через 8 минут и 49 секунд P.S. хотя, конечно, виртуальный деструктор не нужен, лишняя виртуальная функция. Добавлено через 11 минут и 40 секунд То есть виртуальный деструктор нужен, не нужен чисто абстрактный виртуальный деструктор. ![]() Добавлено через 12 минут и 45 секунд Но если он уже виртуальный, то без разницы, чисто абстрактный он или нет. (специально мысли свои не стираю) |
Автор: atomicxp 13.6.2009, 13:18 | ||||||
Значит так, виртуальный деструктор нужен для предотвращения утечек памяти в случае удаления объекта класса, который в свою очередь использовал интерфейс, через указатель на интерфейс, который указывает на объект класса использующий интерфейс. Если кратко, то в случае защищённого деструктора удаление через него невозможно, следовательно утечка памяти тоже невозможна, а значит виртальный деструктор не нужен.
Добавлено через 5 минут и 52 секунды У меня
У math.
Судя по тому, что компилятор выдаёт одни и те же ошибки, даже в пустом определении деструктора нет необходимости. |
Автор: mes 13.6.2009, 13:34 | ||||||||
У создаваемого объекта, каждый деструктор (его и предков) должен иметь тело. Т.е абсолютно чистым его не сделать.
Это вырожденный случай и на практике такое не случается, к тому же обладает скрытым недостатком. (Надо всегда помнить, что у унаследованного от наследника (у которого деструктор будет открыт) такого класса нельзя будет пользоваться полиморфным удалением, или придется все равно добавлять виртуальный деструктор) А стоит ли экономить место под один указатель_на_метод на класс (а не один на объект) ? и из за этой мнимой экономии обрекать себя на скрытые ошибки и неудобства ? Добавлено @ 13:37
Попробуйте создать объект отнаследованного класса ![]() |
Автор: atomicxp 13.6.2009, 14:30 |
В общем, в интерфейсе есть необходимость в пустом блоке объявлении деструктора для удаления объекта использующего в классе интерфейс. Пожалуй на этом и всё, пора переходить к следующим шаблонам проектирования. |
Автор: atomicxp 13.6.2009, 16:55 | ||||||||
Переходим к следующему шаблону проектирования так же принадлжащему к типу основных шаблонов (Fundamental) * Delegation pattern/Шаблон делегирования Оригинальничать не будем, потому сразу определение из вики:
Та же вики сообщает о минусах
Плюсы и применимость не указана, но это и не важно, потому что данный шаблон наиболее часто используемый, так что не требует особых объяснений. Но раз уж я решил обсудить шаблоны, то придётся сделать это и для него. Как уже было сказано, шаблон делегирования, так же известный как техника программирования включение-делегирование, ухудшает чистоту абстракций. Но здесь так же стоит отметить, что подобное негативное влияние можно сократить, а можно наоборот увеличить этот эффект. Под увеличением подразумеваются смешанные классы. Они очень сильно вредят чётким абстракциям. Плюс заключается в возможности перестроения чужих алгоритмов под свои собственные. Таким образом можно перенести целые наборы библиотек. Именно так был построен .NET Framework, ведь рефлектор наглядно показывает, что шаблон делегирования используется в нём чуть ли не чаще, чем всё остальное. Аналогичным образом строится Mono, непроделегированные методы можно просто объявить неиспользуемыми. Если проследить рефлектором историю изменения, то от версии 1.1 к версии 2.0 данная техника программирования стала использоваться для ухудшения абстракций самого дотнета. Хотя речь совсем не о том, в какую сторону двигается майкрософт, а о C++. Простейший пример делегирования:
А вот более интересное использование из вики:
Данный пример намного более интересен, создаются несколько классов и благодаря переключению с помощью интерфейса появляется возможность использовать в одном объекте одними методами совершенно разную реализацию. Конечно, недостаток в том, что приходится переключать весь класс. Так же подобных результатов можно добиться указателями на функции, а не только интерфейсами. Как бы то ни было к шаблону делегирования это не относится. |
Автор: Курсант 13.6.2009, 17:19 |
Чувак, продай мне этой травы, а ![]() ![]() Добавлено через 1 минуту и 6 секунд И не отпускает.. *грустнеет* теперь заминусуют... |
Автор: mes 13.6.2009, 17:28 | ||
так ухудшает или улучшает ? |
Автор: azesmcar 13.6.2009, 17:29 |
atomicxp, Похоже на смесь с контуженным патерном State. |
Автор: atomicxp 13.6.2009, 19:56 | ||
Далее по плану следует Immutable/Неизменяемый объект. Для начала нужно сказать, что неизменяемость объекта достигается различными путями. Как только объект был инициализирован, он уже не должен изменятся с точки зрения пользователя этого объекта, и не важно, чем это выражено. Объект может быть как частично, так и полностью незименямым. Иногда это достигается ключевым словом const, в других случаях закрытыми полями и методом доступа с запретом изменять значения объекта. Простейший случай использования:
Неизменямость хоть и проста в использовании, но требует более детального рассмотрения. |
Автор: atomicxp 13.6.2009, 21:17 |
Рассмотрим для чего же выделять шаблоны проектирования, и как это поможет в реальном деле. Если бы шаблоны проектирования были слишком сильно размыты и их нельзя выделить в стереотипы, нам бы незачем было о них говорить. Взглянем на UML отображение класса, которое я сделал.![]() Стереотипы традиционно выделяются в <<>>, а # означает закрытый. Стереотип <<Immutable>> в данном случае отнёс вовсе не к классу, а к методу. Иными словами шаблоны проектирования бывают разными и относятся к разным частям класса. Поскольку уже было рассмотрено три шаблона, то возникает вопрос, можно ли комбинировать какие-либо из них. Если взять тот же интерфейс, то его стереотип был бы записан наверху, заместо слова <<stereotype>> находилось бы <<Interface>>. А вот шаблон делегирования и неизменяемости относятся к методам, особенно если исходить, что включённые (агрегированные) объекты брать всегда используя методы, а сами объекты делать закрытыми или защищёнными. Иными словами пользоваться свойствами (присвоение или извлечение объекта с проверкой), ведь даже там где они имеют другой вид, например, .NET, на самом деле создаются методы с приставкой get/set. Может ли в методе быть <<immutable delegation>>, очевидно да. Даже в таких размытых шаблонах проектирования можно добиться определённости. Причём как видно, некоторые шаблоны этих же категорий, а так же многих других, имеют более чёткое определение и вообще не комбинируются вместе. |
Автор: Курсант 14.6.2009, 15:05 |
Знал я одного атомика из Удмуртии... Жека, это не ты случайно? ![]() Добавлено через 53 секунды Тоже атомик.. Тоже из удмуртии.. Тоже программер великий.. |
Автор: unicuum 14.6.2009, 16:09 |
http://forum.vingrad.ru/topic-257821.html ![]() |
Автор: atomicxp 14.6.2009, 16:13 | ||||
Нет, не я. ![]() Ладно, надоели мне эти фундаментальные шаблоны, к тому же никому они неинтересны, сейчас скопом их опишу и дальше двинусь. Основные шаблоны (Fundamental) * Delegation pattern/Шаблон делегирования * Functional design/Шаблон функционального дизайна * Immutable/Неизменяемый объект * Interface * Marker interface * Property Container Property Container/Контейнер свойств Ниже представлен простейший пример с закрытым значением поля, который хранит свойство. Два метода, один называется accessor, имеет приставку get и извлекает значение. Другой называется mutator, имеет приставку set и изменяет значение.
Так же стоит отметить, что в реальности данные могут хранится где угодно, не обязательно в закрытом поле, и быть в любом виде. За их проверку и перобразование отвечает accessor и mutator, в простейшем случае я не стал использовать дополнительные возможности, которые они предоставляют. В сложных случаях могут использоватся инструкции ветвления, а так же выбрасываться исключения. |
Автор: unicuum 16.6.2009, 13:33 | ||
Даже не хочу это комментировать:
|
Автор: Леопольд 17.6.2009, 15:19 |
Hi atomicxp, Почему-то у меня складывается ощущение что Вам стоит перечитать Страуструпа и прочитать Скота Мейерса "55 способов...", хотя бы. Могу аргументировать это только тем, что Ваши посты могли бы быть больше связанными со спецификой С++. Иногда, складывается ощущение что Вы не совсем понимаете как работает С++. К примеру, в целях проектирования на С, можно использовать разницу между статической и динамической компоновкой/линковкой обычных функций для имитации инкапсуляции. В С++ есть поиск функции по аргументу, уверен тоже можно куда-нибудь присобачить... ![]() 1. "Шаблоны. Справочник разработчика" David Vandevoorde, Nicolai M. Josuttis 2. "Современное проектирование на С++" Александреску (именно в этом порядке) Я сам ещё 1-ю не прочитал, но уже понял что надо обязательно дочитать... Если же ближе к теме, то моё мнение о паттернах проектирования следующее: 1. Прочитать и понять идеи опытных разработчиков, спроектировавших с их помощью серьёзный и крупный софт, очень полезно. 2. Зная о смысле паттернов, можно применять их на практике хоть на ассемблере, всё зависит от того, насколько сильно Вы готовы абстрагироваться от конструкций языка, которые вы будете называть реализацией паттерна. 3. Пользоваться чужими идеями нужно обдуманно, а совсем не пользоваться своими просто глупо. Уверен, что с этим согласится человек любой профессии. Показатель способностей разработчика софта - уметь решать подобные головоломки. Уверен многим именно поэтому нравится своя работа. По этим причинам я думаю что нет особого смысла пытаться реализовать каждый паттерн на каком либо языке. Если знаешь язык то это не составит труда, главное знать что хочешь реализовать. К тому же, следует учесть что иногда приёмы программирования устаревают или хуже того, встраиваются в синтаксис языка. ![]() |
Автор: atomicxp 17.6.2009, 22:37 | ||||
Именно с него всё это и пишу, "Язык программирования C++ 3-е издание", у меня бумажная версия с 1999 года, и пожалуй эту книгу я уважаю больше всех по тематике C++. То что пока тут написал относится к главам с 10 по 15 - механизмы абстракции.
Первое не читал, второе читал. Сразу стоит отметить, что у Александреску другой подход, не такой как у Страуструпа, а я больше склоняюсь к идеям последнего. К тому же я не заставляю людей пользоваться тем, что описал. Это не более чем мысли вслух, большая часть которых остаётся невысказанной. В рассуждениях уже докатился до универсальной абстракции с которой можно построить абстракцию для построения программ на реальных объектно-ориентированных системах программирования, в основе которые даже не важно какой язык, C++, Java, C# или что-то другое. |
Автор: Леопольд 18.6.2009, 07:35 | ||||
Первая книга в деталях объясняет шаблоны. Вторая показывает как можно их использовать. Без понимания первой, понять вторую достаточно проблематично, хотя, конечно, возможно, но поверхностно. Приниматься за проектирование на любом языке стоит только после изучения его возможностей. Шаблоны не следует упускать из виду... По поводу книжки Страуструпа - шаблоны и их возможности, затронуты недостаточно глубоко. Я думаю, ему просто не хватило места. Объём книги мог увеличится как минимум в полтора раза. А Мейерса всё же стоит почитать. Тем более, читатется лекго и непринуждённо, после Страуструпа. ![]() В общем, следует иметь ввиду что в книжке Страуструпа описанно не всё. Насколько я помню (читал эту книгу два года назад), он недостаточно детально объяснил раздельную компиляцию. Про предкомпилированные заголовочные файлы ни слова не сказанно (полагаю, для шаблонов это имеет серьёзное значение). Не думаю что я перечислил всё что он "упустил", это первое что пришло в голову. |
Автор: atomicxp 18.6.2009, 13:22 | ||
Стоит, это одна из книг которую бы я тоже рекомендовал для прочтения.
Приведи пример в коде. У Страуструпа так плотно записано множество идей, техник, правил, и много всего, что даже после десяток прочтений находишь нечто новое. В целом же работа с заголовочными файлами достаточно подробна описана в главе 9. Конечно нет, но заметь, что есть шаблоны функций, и шаблоны классов, и в зависимости от того, что программист берёт в основу, получающаяся система координально различается. Для того чтобы выполнить операцию, не обязательно связывать её с конкретным объектом, в котором она чаще всего воздействует на этот объект, то есть на агрегированные члены этого или базовых классов. Иногда это менее очевидно, например, в классе приложения может быть метод - запустить окно в потоке приложения. Иногда более, в классе списка, добавить элемент в список. Хотя, общая черта куда засунуть тот или иной метод я думаю уже видна из моих примеров. Здесь так же стоит отметить, что STL и Boost это стиль Александреску, то есть там нет чёткого разделения указанного выше. Мне это больше напоминает модульное программирование, когда есть классы заключающие в себе наборы функций вне зависимости от принадлежности, или вообще находящиеся в глобальном пространстве имён. |
Автор: Lazin 18.6.2009, 13:59 | ||
это как? давай на конкретных примерах, а то у меня нет времени все это читать |
Автор: unicuum 18.6.2009, 14:41 | ||
Ну давай. Обычно когда люди берут STL, они сбрасывают пространство имён std до глобального. Проблема в том, что каких-либо ещё уровней вложения особо и не предусмотрено. Даже если каждый раз писать std:: с точки зрения проектирования это ничем не отличается от глобального пространства, максимум может дать защиту от пересечений с собственной библиотекой программиста. Перейдём к организации стандартной библиотеки шаблонов. В ней присутствуют шаблоны условно разделённые на группы, алгоритмы, ввод/вывод, итераторы, контейнеры, строки, утилиты, числа и так далее. Взять хотя бы первое - алгоритмы, это уж явно не объектно-ориентированное программирование. Если вглядеться внутрь, то увидим - немодифицирующие операции с последовательностями, модифицирующие операции с последовательностями, сортировка последовательностей, работа со множествами, операции с кучей, минимумы и максимумы, перестановки. Всё это наборы операций, и при рассмотрении многих других групп видна та же картина. Не абсолютно везде конечно, но в подавляющей части уж точно. Это всё архитектурные составляющие, так спроектировали библиотеку. Мне думается влияние на это оказал Си, то есть пытались сделать некое промежуточную библиотеку, которая позволила бы Си программистам перейти на C++, вот только в Си нет классов. |
Автор: mes 18.6.2009, 15:05 | ||||||||||||
Это проблема людей, а не библиотеки
Это тоже библиотеку никоем образом не касается
А какую защиту Вы еще хотите ?
Да это не ООП, это следующий уровень абстракции.
Нет, то что Стл такая, это влияние Степанова ![]()
|
Автор: Lazin 18.6.2009, 15:48 | ||||
Объясни мне, как ты собираешься реализовать в ООП стиле алгоритм sort, или for_each? Если следовать твоей логике, то нужно каждому контейнеру добавить метод sort, да? Вот теперь смотри, тебе понадобится по одному методу sort без параметров а так-же по методу sort(iterator iterator)(так-как мне может понадобиться отсортировать только часть данных), для каждого типа контейнера. Дальше, это все будет работать для контейнеров, но не будет работать для обычных указателей. Потом, разработчики, реализующие свои контейнеры, должны будут реализовать эти методы для своих контейнеров, если они хотят, что-бы они были stl совместимы. А еще у нас не один алгоритм sort, у нас много разных алгоритмов. Если ты знаком с комбинаторикой, то ты сможешь представить сколько кода придется написать только для stl, а сколько кода придется писать другим разработчикам - вряд-ли сможешь ![]() Это плохой дизайн. В то-же время в STL все это сделано очень просто. У каждого контейнера есть методы возвращающие пару итераторов: begin и end, эти итераторы могут быть разных категорий - ForwardIterator, ReverseIterator, RandomAccessIterator. На этапе компиляции можно выяснить, к какой категории принадлежит этот итератор с помощью класса std::iterator_traits, а так-же с его помощью можно получить тип значения или ссылки. Это так-же работает для обычных указателей. Алгоритмы принимают итераторы(которые могут быть чем угодно) и получают все нужные им типы данных с помощью iterator_traits, они могут быть реализованы по разному для разных типов итераторов. В итоге мы имеем следующее: не ООП алгоритмы работают с чем угодно; они могут быть специализированы для разных частных случаев; они могут работать с классами о которых разработчики стандартной библиотеки не имели представления; разработчикам достаточно написать класс - итератор для своих классов коллекций и все алгоритмы будут работать для их классов; можно писать STL совместимые алгоритмы, которые будут работать так-же как и стандартные, к примеру можно реализовать radix_sort, который будет работать с std::vector<..>, в случае, если алгоритмы будут методами - это будет невозможно. Одним словм, это правильный дизайн. ![]()
во первых то, что есть в std зависит от того, какие заголовочные файлы подключены, во вторых, пространство имен std можно расширять, к примеру новыми алгоритмами, или можно специализировать iterator_traits для своего итератора и так далее ![]() |
Автор: azesmcar 18.6.2009, 16:32 | ||||||
![]() кстати - std::string прекрасный пример того, чтобы произошло если
а если быть точнее - логике unicuum. Саттера в своей книге more exceptional C++ упоминает об этом. Сколько там функций было? 44 кажется, не помню точно. Так вот, очень многие из этих функций можно было бы вынести за рамки класса, и это было бы правильнее. Например функция empty(). Она написана в каждом контейнере отдельно, хотя могла бы быть одна на всех.
там много чего написано, не хочу сейчас все цитировать. Но СТЛ даже более обьектен чем следовало бы. |
Автор: unicuum 18.6.2009, 17:33 | ||
Не нужно комбинировать больше семи членов, сначало делают, потом удивляются что ООП уродское, а это не ООП на самом деле.
Это всё понятно, но сейчас у тебя идёт речь о шаблонах, и о том, что они дают мощь при компиляции генерируя функции, классы и всё что угодно, уменьшая при этом код разработчиков. С этим согласен, это хороший способ писать как можно меньше, но к самому ООП и его парадигме это не имеет отношения и самое главное ей нисколько не противоречит. Главный принцип ООП характеризовал бы как - "Разделяй и властвуй". Не нужно забывать, что методы классов можно сделать статическими, не обязательно использовать их через объект. Здесь дело в логической связи между тем, что лежит в одном классе, именно тот самый шаблон функционального дизайна описанный выше - класс должен отвечать за минимальную область деятельности. Чтобы скомбинировать методы в одном классе, они должны быть по настоящему связаны. Если таких классов наберётся много за связь должны отвечать пространства имён, но не нужно пытаться выполнить их роль, за счёт засовывания методов в один класс. |
Автор: mes 18.6.2009, 17:47 | ||
откройте для себя АОП : http://ru.wikipedia.org/wiki/%D0%90%D1%81%D0%BF%D0%B5%D0%BA%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5 может тогда получится понять, что ООП это не панацея. ![]() P.S. Вы зачастую приводите чужую одностороннюю точку зрения, забывая что каждый кулик свое болото хвалит. ![]() |
Автор: unicuum 18.6.2009, 18:07 | ||
То что стилей много это и так понятно, но в этой теме даже обсуждаемые шаблоны проектирования принадлежат именно к объектно-ориентированному программированию. Если кому-то интересна другая точка зрения на процесс программирования в целом, то же аспектно-ориентированное программирование, то им надо заводить отдельный топик и там общаться. |
Автор: mes 18.6.2009, 18:17 | ||||
Не принадлежат, а рассмотрены с точки зрения ООП. ![]() ![]() Добавлено @ 18:20
P.S. другую точку зрения я привел не для ее обсуждения, а для того, чтоб лучше могли представить достоинства и недостатки обсуждаемой т.з. |
Автор: Lazin 18.6.2009, 19:31 | ||||||||||||
тебе не кажется
что ты сам себе противоречишь?
![]() и где интересно я выступаю против ООП? ![]()
а почему именно 7, а не 8? ![]() а если мне нужно перегрузить метод для множества разных аргументов, это по уродски или нет? ![]()
![]() статическим, метод может быть тогда, когда он не использует данные экземпляра объекта, а если использует, то ты только усложнишь себе жизнь...
пространства имен это фикция, в ООП нет такого понятия, это синтаксический сахар ![]() ты не видишь разницу между реальноми возможностями языка программирования и синтаксическим сахором, который призван улучшить читаемость кода ![]() вообще, обсуждение ушло куда-то не туда, лично я готов обсуждать что-либо имеющее отношение к практике, к примеру какой-либо случай применения определенного паттерна, а пустая болтовня только зря отнимает время ![]() |
Автор: zim22 18.6.2009, 19:46 | ||||||||||||||||||||||
"Совершенный код" Макконнелл (стр.140) 6.3. Вопросы проектирования и реализации подпункт Включение (отношение "содержит")
*** unicuum и atomicxp очень любят число СЕМЬ! ![]() привожу их цитаты:
*** интересно проследить, как рекомендация стала правилом: Макконнелл:
atomicxp | unicuum
![]() |
Автор: unicuum 18.6.2009, 19:59 | ||
Ну, это я один на самом деле, хотя не важно. ![]() |
Автор: mes 18.6.2009, 20:11 |
Кроме того рекомендация была переврана, и дата-члены превратились в сущности (в контексте высказывания также методы) Более того рекомендация эта относилась к людям, которые не чувствуют, что такое объект и нужна лишь для их обучения, но никак не для слепого следования этому "правилу". ![]() |
Автор: atomicxp 18.6.2009, 20:54 | ||
На самом деле поля не нужно группировать по этому правилу, если только не объявить их открытыми, о чём было сказано при обсуждении контейнеров свойств, потому что контейнер будет засчитываться за одно понятие. К тому же в данном случае всё это так же относится и к пространствам имён, которые тоже могут быть вложены одни в другие. Кто-то может сказать, что это всё соблюдать при проектировании программ не нужно, но так же можно утверждать, что ООП бесполезен и использовать вместо него что угодно. Самой программе без разницы, что о ней думают её создатели, она просто выполняется. Эти правила нужны лишь программистам, чтобы писать более эффективные и надёжные программы. |
Автор: mes 18.6.2009, 21:16 | ||||||||
без комментов ![]()
Если это намек в мою сторону, то я говорил, что не надо фанатизма, а нужно подходить ко всему с головой. 1. ООП не бесполезен, но он же и не всемогущ, 2. Cpp больше, чем ООП ![]()
Вы забыли еще об одной стороне. Программе требуется развитие и сопровождение - и в этом вопросе ей не все равно ![]() (программы одноневки не рассматриваются по вполне понятным причинам) ![]()
Ваше "правило" о семи сущностях к этому не относится. Это такое же, как "правило похудания" не покупать еды, больше чем на N(не помню число) рублей в день. ![]() |
Автор: Леопольд 18.6.2009, 22:31 |
Вот есть у на автомобиль. А еще у нас есть кондиционер. Всё, раз так, то нельзя совмещать кондиционер и автомобиль потому что они разные... А автомобиль в кондиционере, это же вообще смешно! ![]() Что мешает смешивать техники с успехом? Нельзя зацикливаться на чём-то одном. Это не путь к успеху. Надо уметь мыслить гибко. Для пущей эффективности, стоит изучить "велосипеды", что бы не изобрести в результате своих усиленных размышлений самокат ![]() Я ещё не слишком отступил от основной темы? ![]() Даже рассуждая так примитивно, можно прийти к выводу что ограничивая себя только лишь одной технологией (живой пример бензиновые двигатели) развитие достигает своего потолка. Дальше можно пройти только изобретая что-то новое. Языки программирования и способы проектриования превратились в отдельную, пока ещё не признанную науку. Но это не значит что на них не распространяется это общее правило. ООП не аскиома в проектирование. Технология весьма полезная, но не единственная... Способы проектированя с использованием ООП весьма интересны и эффективны. Но не надо пытаться заменить процедурную часть программы на объектную (алгоритмы STL, например) только лишь потому что C++ поддерживает такую абстракцию синтаксически. Напомоню что это далеко не все его возможности. Это как ездить на автомобиле с кондиционером но вместо него, в жару, открывать люк на крыше (формой, подозрительно, напоминающий автомобиль), причём выпиленный своими руками на прошлой неделе. К сожалению, что-бы творчество могло быть продуктивным и действительно кому-нибудь интересным, надо очень много учить... С++ чрезвычано богатый возможностями язык. |
Автор: atomicxp 20.6.2009, 02:21 |
Шаблоны бесполезны в отрыве от их сферы применения. Можно пытаться определить, какой из них используешь постфактум, но это принесёт гораздо меньше пользы, и уж точно не поможет в проектировании, а только в исправлении реализации и приведения её к эталонному виду. Значит если описывать шаблоны по порядку, то это ничего не даст. В таком случае неверное придётся вначале объявить заголовочный файл, а детали реализации оставить на потом. Шаблоны проектирования Основные шаблоны (Fundamental) * Delegation/Делегирование (перепоручение): Передача ответственности за выполнение связанному объекту * Encapsulation or Information hiding/Инкапсуляция или Сокрытие данных: Предоставляет косвенные методы манипулирования данными объекта или класса, вместо манипуляции напрямую * Event Channel/Канал событий: Производит, выявляет, использует и реагирует на события. * Exceptions/Исключения: Поддерживает языковой механизм исключений * Functional design/Функциональный дизайн: Каждый класс программы имеет только одну функциональность * Immutable/Неизменяемый: Объект, который нельзя изменить после его создания * Inheritance or subclassing: Наследует методы от родительского класса для повторного использования кода * Interface/Интерфейс: Обеспечивает доступ к методам других классов * Marker interface: Позволяет получить информацию об объектах во времени исполнения * Property Container: Посредник между полями и методами класса Порождающие шаблоны проектирования * Abstract Factory/Абстрактная фабрика, Kit (GoF): Позволяет изменять поведение системы, варьируя создаваемые объекты, при этом сохраняя интерфейсы * Anonymous subroutine objects: * Builder/Строитель (GoF): Отделяет конструирование сложного объекта от его представления, так что в результате одного и того же процесса конструирования могут получаться разные представления * Creator/Создатель экземпляров класса (GRASP): Решает кто должен создавать объект * Factory Method/Фабричный метод, Virtual Constructor/Виртуальный конструктор (GoF): Предоставляет подклассам интерфейс для создания экземпляров некоторого класса * Lazy initialization/Отложенная инициализация: Ресурсоёмкая операция выполняется только непосредственно перед тем, как будет использован её результат * Multiton/Мультитон: Гарантирует, что класс имеет поименованные экземпляры объекта и обеспечивает глобальную точку доступа к ним * Object Pool/Объектный пул: Использование заранее инициализированных объектов * Prototype/Прототип (GoF): Задаёт виды создаваемых объектов с помощью экземпляра-прототипа и создаёт новые объекты путём копирования этого прототипа * Resource acquisition is initialization: Гарантирует, что ресурсы высвобождаются при освобождении объектов использующих их * Singleton/Одиночка (GoF): Гарантирует, что у класса одновременно может быть только один экземпляр объекта и обеспечивает глобальную точку доступа к нему Структурные шаблоны классов/объектов (Structural) * Adapter/Адаптер, Wrapper (GoF): Организует использования функций объекта, недоступного для модификации, через специально созданный интерфейс * Bridge/Мост, Handle/Описатель, Body/Тело (GoF): Разделяет абстракцию и реализацию так, чтобы они могли изменяться независимо * Composite/Компоновщик (GoF): Объединяет объекты в древовидную структуру для представления иерархии от частного к целому * Container * Decorator/Декоратор, Wrapper/Оболочка (GoF): Предназначен для динамического подключения дополнительного поведения к объекту * Extensibility * Information Expert/Информационный эксперт (GRASP): Обязанности должны быть назначены объекту, который владеет максимумом необходимой информации для её выполнения * Facade/Фасад (GoF): Позволяет скрыть сложность системы путем сведения всех возможных внешних вызовов к одному объекту, делегирующему их соответствующим объектам системы * Flyweight/Приспособленец (GoF): Используется для уменьшения затрат при работе с большим количеством мелких объектов * Low Coupling/Низкая связанность (GRASP): Малое число зависимостей между классами, высокая степень повторного использования подсистем * Pipes and filters * Private class data * Protected Variations/Сокрытие реализации (устойчивый к изменениям) (GRASP): Защищает элементы от изменения других элементов (объектов или подсистем) с помощью вынесения взаимодействия в фиксированный интерфейс * Proxy/Заместитель, Surrogate (Суррогат) (GoF): Предоставляет объект, контролирующий доступ, перехватывая все вызовы к нему Поведенческие шаблоны классов/объектов (Behavioral) * Blackboard: Обобщённый наблюдатель позволяющий множество считывающих и записывающих * Chain of Responsibility/Цепочка ответственности (GoF): Предназначен для организации в системе уровней ответственности * Command/Команда, Action/Действие, Transaction/Транзакция (GoF): Заключает в себе действие и его параметры. * Controller/Контроллер (GRASP): Берёт на себя ответственность за выполнение операций, приходящих от пользователя * Don't talk to strangers/Не разговаривайте с неизвестными (GRASP) * High Cohesion/Высокое зацепление (GRASP): Cильное сцепления внутри подсистем классов * Indirection/Перенаправление (GRASP): Поддерживает слабую связанность и возможность повторного использования путём назначения обязанностей посредника между ними промежуточному объекту * Interpreter/Интерпретатор (GoF): Представляет грамматику языка и интерпретацию * Iterator/Итератор, Cursor (GoF): Позволяет последовательный доступ к элементам объекта-агрегата без использования описаний каждого из объектов, входящий в состав агрегации * Mediator/Посредник (GoF): Помогает организовать взаимодействие систем, имеющих дело с разнородными источниками данных * Memento/Хранитель, Token (GoF): Не нарушая инкапсуляцию сохраняет во вне состояние объекта для его последующего восстановления * Null Object/Нулевой объект: Сбрасывает значение по умолчанию в ноль * Observer/Наблюдатель, Dependents, Publish-Subscribe, Event listener (GoF): Определяет зависимость типа «один ко многим» между объектами таким образом, что при изменении состояния одного объекта все зависящие от него оповещаются об этом событии * Polymorphism/Полиморфизм (GRASP): Позволяет обрабатывать альтернативные варианты поведения на основе типа и заменять подключаемые компоненты системы * Pure Fabrication/Чистая выдумка (искусственный) (GRASP): Не отражающий никакого реального объекта предметной области, но специально придуманный для усиления связности, ослабления связанности или увеличения степени повторного использования * Restorer/Восстановитель: Альтернатива шаблону хранителю * Simple Policy * Specification: Перекомбинирует бизнес логику в булевы образы * State/Состояние, Objects for States (GoF): Используется в тех случаях, когда во время выполнения программы объект должен менять свое поведение в зависимости от своего состояния * Strategy/Стратегия (GoF): Предназначен для определения семейства алгоритмов, инкапсуляции каждого из них и обеспечения их взаимозаменяемости * Template Method/Шаблонный метод (GoF) * Visitor/Посетитель, Single-serving visitor, Hierarchical visitor (GoF) Шаблоны параллельного программирования (Concurrency) * Active Object/Активный объект: Отделяет методы исполнения от ссылочных методов, которые находятся в их собственных потоках управления * Balking: Программный шаблон проектирования, который исполняет действия над объектами, только когда они находятся в особенном состоянии * Binding Properties/Связанные свойства: Сочетает множество наблюдателей влияющих на свойства различных объектов, для синхронизации или координирования в некотором направлении * Double checked locking: Предназначен для снижения накладных расходов на первое тестирование блокировки в небезопасной манере * Event-Based Asynchronous: Базируется на событиях адресов проблем с асинхронным шаблоном происходящим в многопоточных программах * Guarded suspension/Охраняемая приостановка: Управляет операциями, которые требуют и приобретённой блокировки, и удовлетворяющего предусловия до их исполнения * Half-Sync/Half-Async * Leaders/followers * Lock/Блокировка: Один поток ставит блокировку на ресурс предотвращая доступ или изменение с других потоков * Monitor Object/Объектный монитор:Подход к синхронизации двух или более компьютерных задач, которые используют общие ресурсы, обычно аппаратные устройства или наборы переменных * Reactor: Используется для обработки служебных запросов доставленных параллельно обработчикам служб в один или более входов * Read write lock: Допускает одновременный доступ на чтение к объекту, но требует монопольный доступ на операции записи * Scheduler/Планировщик: Используется для явного управления, когда потоки могут исполнять однопотоковый код * Thread pool/Пул потоков: Некоторое количество созданных потоков для выполнения ряда задач, которые обычно организованы в очереди * Thread-Specific Storage: Представляет программный метод, который использует статичную или глобальную память в локальном потоке * Single Thread Execution MVC * Model-View-Controller/Модель-представление-контроллер * Model-View-Presenter * Presentation-Abstraction-Control Enterprise * Business Delegate: Прячет сложности поиска и создания бизнес-сервисов * Composite Entity/Составная Сущность: Обеспечивает обмен данными между слоями, уменьшая сетевой трафик * Composite View: Созданёт составное визуальное представление * Data Access Objec(DAO)/Объект Доступа к Данным: Абстрагирует источник данных; обеспечивает прозрачный доступ к данным * Dispatcher View: Описывает особую комбинацию контроллера и диспетчера с видами и хелперами * Front Controller: Комбинирует Dispatcher, Front Controller и View Helper, откладывая обработку сигналов. * Intercepting Filter: Обеспечивает централизованную точку входа для управления обработкой запроса * Service Activator: Обеспечивает асинхронную обработку для компонентов EJB * Service Locator/Локатор Службы: Управляет исполнением запросов, кэшированием результатов и их обработкой * Service to Worker: Описывает особую комбинацию контроллера и диспетчера с видами и хелперами * Session Facade/Фасад Сессии: Разделяет презентационный и сервисный уровни, обеспечивает интерфейсы фасада и посредника для сервисов * Transfer Object Assembler(Value Object Assembler): Прячет сложность бизнес-объекта, централизует обработку workflow * Transfer Object(Value Object)/Объект Перемещения: Прячет сложность бизнес-объекта, централизует обработку workflow * Value List Handler/Обработчик Списка Значений: Собирает составной Value Object из многих источников данных * View Helper: Обеспечивает предварительную и пост-обработку запроса Архитектурные структурные шаблоны * Repository/Хранилище * Client/Server/Клиент/сервер * Domain Model/Модель предметной области, Data Mapper/Модуль таблицы * Layers/Многоуровневая система (абстрактная машина) * Data Streams/Потоки данных (конвейер или фильтр) Архитектурные шаблоны централизованного управления * Вызов - возврат (сценарий транзакции - частный случай) * Диспетчер Архитектурные шаблоны событийного управления * Передача сообщений * Управляемый прерываниями Архитектурные шаблоны взаимодействие с базой данных * Active Record/Активная запись * Unit Of Work/Единица работы * Lazy Load/Загрузка по требованию * Identity Map/Коллекция обьектов * Record Set/Множество записей * Single Table Inheritance/Наследование с одной таблицей * Class Table Inheritance/Наследование с таблицами для каждого класса * Optimistic Offline Lock/Оптимистическая автономная блокировка * Отображение с помощью внешних ключей * Association Table Mapping/Отображение с помощью таблицы ассоциаций * Pessimistic Offline Lock/Пессимистическая автономная блокировка * Identity Field/Поле идентификации * Data Mapper/Преобразователь данных * Client Session State/Cохранение сеанса на стороне клиента * Server Session State/Cохранение сеанса на стороне сервера * Row Data Gateway/Шлюз записи данных * Table Data Gateway/Шлюз таблицы данных Структурные шаблоны интеграции информационных систем * Взаимодействие "точка - точка" * Взаимодействие "звезда" (интегрирующая среда) * Смешанный способ взаимодействия Шаблоны интеграции информационных систем по методу * Data-Centric/Интеграция систем по данным * Function-Centric/Функционально-центрический подход * Object-Centric/Объектно-центрический подход * Concept-Centric/Понятийно-центрический подход Шаблоны интеграции информационных систем по типу обмена данными * Файловый обмен * Общая база данных * Удаленный вызов процедур * Обмен сообщениями Антишаблоны проектирования Управление разработкой ПО * Smoke and mirrors/Дым и зеркала: Демонстрация того, как будут выглядеть ненаписанные функции (название происходит от двух излюбленных способов, которыми фокусники скрывают свои секреты). * Software bloat/Раздувание ПО: Разрешение последующим версиям системы требовать всё больше и больше ресурсов. * Options checkbox/Функции для галочки: Превращение программы в конгломерат плохо реализованных и не связанных между собой функций (как правило, для того, чтобы заявить в рекламе, что функция есть). Разработка ПО * Abstraction inversion/Инверсия абстракции: Создание простых конструкций поверх сложных (спорный) * Ambiguous viewpoint/Неопределённая точка зрения: Представление модели без спецификации её точки рассмотрения * Big ball of mud/Большой комок грязи: Система с нераспознаваемой структурой * Blob/Блоб, God object/Божественный объект: Объект, который хранит в себе слишком много, или делает слишком много * Gas factory/Бензиновая фабрика: Необязательная сложность дизайна * Input kludge/Затычка на ввод данных: Забывчивость в спецификации и выполнении поддержки возможного неверного ввода * Interface bloat/Раздувание интерфейса: Изготовление интерфейса очень мощным и очень трудным для осуществления * Magic pushbutton/Магическая кнопка: Выполнение результатов действий пользователя в виде неподходящего (недостаточно абстрактного) интерфейса. * Re-Coupling/Перестыковка: Процесс внедрения ненужной зависимости * Stovepipe system/Дымоход: Редко поддерживаемая сборка плохосвязанных компонентов * Race hazard(Race condition)/Гонки: Ошибка в определении последовательности различных порядков событий Объектно-ориентированное программирование * BaseBean/Базовый класс-утилита: Наследование функциональности из класса-утилиты вместо делегирования к нему * CallSuper/Вызов предка: Для реализации прикладной функциональности методу класса-потомка требуется в обязательном порядке вызывать те же методы класса-предка. * Empty subclass failure/Ошибка пустого подкласса: Создание класса (Perl), который не проходит «проверку пустоты подкласса» («Empty Subclass Test») из-за различного поведения по сравнению с классом, который наследуется от него без изменений * God object/Божественный объект: Концентрация слишком большого количества функций в одиночной части дизайна (классе) * Object cesspool/Объектная клоака: Переиспользование объектов, чьё состояние не удовлетворяет (возможно неявному) контракту переиспользования. * Poltergeist/Полтергейст: Объекты, чьё единственное предназначение — передавать информацию другим объектам * Yo-yo problem/Проблема йо-йо: Структура (например: наследования) которая тяжело понятна вследствие избыточной фрагментации * Singletonitis/Синглетонизм: Избыточное использование паттерна синглетон Программирование * Accidental complexity/Ненужная сложность: Внесение ненужной сложности в решение * Action at a distance/Действие на расстоянии: Неожиданное взаимодействие между широко разделёнными частями системы * Accumulate and fire/Накопить и запустить: Установка параметров подпрограмм в наборе глобальных переменных * Blind faith/Слепая вера: Недостаточная проверка (a) корректности исправления ошибки или (b) результата работы подпрограммы * Boat anchor/Лодочный якорь: Сохранение более не используемой части системы * Busy spin/Активное ожидание: Потребление ресурсов ЦПУ (процессорного времени) во время ожидания события, обычно при помощи постоянно повторяемой проверки, вместо того, чтобы использовать систему сообщений * Caching failure/Кэширование ошибки: Забывать сбросить флаг ошибки после её обработки * Checking type instead of membership(Checking type instead of interface)/Проверка типа вместо интерфейса: Проверка того, что объект имеет специфический тип в то время, когда требуется только определённый интерфейс * Code momentum/Инерция кода: Сверхограничение части системы путём постоянного подразумевания её поведения в других частях системы * Coding by exception/Кодирование путём исключения: Добавление нового кода для поддержки каждого специального распознанного случая * Cryptic code/Таинственный код: Использование аббревиатур вместо полных (самоописывающих) имён * Hard code/Жёсткое кодирование: Внедрение предположений об окружении системы в слишком большом количестве точек её реализации * Soft code/Мягкое кодирование: Патологическая боязнь жёсткого кодирования, приводящая к тому, что настраивается всё что угодно, при этом конфигурирование системы само по себе превращается в программирование. * Lava flow/Поток лавы: Сохранение нежелательного (излишнего или низкокачественного) кода по причине того, что его удаление слишком дорого или будет иметь непредсказуемые последствия * Magic numbers/Магические числа: Включение чисел в алгоритмы без объяснений * Procedural code/Процедурный код: Когда другая парадигма является более подходящей * Spaghetti code/Спагетти-код: Системы, чья структура редко понятна, особенно потому что структура кода используется неправильно * Soap bubble/Мыльный пузырь: Класс, инициализированый мусором, максимально долго притворяется, что содержит какие-то данные. Методологические анти-паттерны * Copy and paste programming/Программирование методом копирования-вставки (китайский код): Копирование (и лёгкая модификация) существующего кода вместо создания общих решений * De-Factoring/Дефакторинг: Процесс уничтожения функциональности и замены её документацией * Golden hammer/Золотой молоток: Сильная уверенность в том, что любимое решение универсально применимо. Название происходит от английской поговорки «когда в руках молоток, все проблемы кажутся гвоздями». * Improbability factor/Фактор невероятности: Предположение о невозможности того, что сработает известная ошибка * Premature optimization/Преждевременная оптимизация: Оптимизация на основе недостаточной информации * Reinventing the wheel/Изобретение колеса: Ошибка адаптации существующего решения * Reinventing the square wheel/Изобретение квадратного колеса: Создание плохого решения, когда существует хорошее Управление конфигурацией * Dependency hell/Ад зависимостей: Проблемы с версиями требующихся продуктов, особенно в системах UNIX/GNU/Linux * DLL hell/DLL-ад: Проблемы с версиями, доступностью и увеличением количества DLL, особенно в Microsoft Windows. Некоторые организационные анти-паттерны * Analysis paralysis/Аналитический паралич: Выделение непропорционально больших усилий в фазе анализа проекта * Cash cow/Дойная корова: Закрытый продукт, приносящий выгоду, часто ведёт к самоуспокоенности относительно новых продуктов * Continuous obsolescence/Продолжительное устаревание: Выделение непропорционально больших усилий портированию системы в новые окружения * Cost migration/Сваливание расходов: Перенос расходов на проект к уязвимому отделу или бизнес-партнёру * Creeping featurism/Ползущий улучшизм: Добавление новых улучшений в ущерб качеству системы * Design by committee/Разработка комитетом: Результат того, что имеется много содействующих разработке, но не имеется единого видения * Escalation of commitment/Эскалация обязательств: Продолжение реализации решения в том случае, когда неправильность его доказана. * I told you so/Я тебе это говорил: Когда игнорируется предупреждение эксперта, являющееся оправданным * Management by numbers/Управление числами: Уделение избыточного внимания численным критериям управления, когда они неважны или стоимость их получения слишком высока * Management by perkele/Драконовские меры: Военный стиль управления без толерантности к диссидентству * Mushroom management/Управление грибами: Удержание работников в неинформированном и занятом состоянии * Scope creep/Расползание рамок: Дозволение рамкам проекта расти без должного контроля * Vendor lock-in/Замкнутость на продавце: Изготовление системы, избыточно зависящей от внешнего поставляемого компонента * Warm body/Тёплое тело: Человек, чей вклад в проект под сомнением, особенно если рассмотрен в панике * Single head of knowledge/Единственный знающий человек: ЕЗЧ (SHOK) применим в том случае, когда единственная личность во всей организации контролирует жизненно-важную область ноу-хау или информации о внутренностях системы. * Knight in shining armor/Рыцарь на белом коне: РНБК (KISA) происходит тогда, когда личность, которая не совершает ошибок, появляется на сцене и пытается починить всё, без сообщений о том, какие изменения он/она сделал/сделает и почему. Социальные взаимотношения * Censorship/Цензура: Подавление дискуссии для предотвращения политического, социального и научного прогресса * Concentrated power(Political corruption)/Концентрация власти: Индивидуальное злоупотребление властью, даже с изначально хорошими помыслами * Democracy/Демократия: Большая группа индивидов не может принимать аргументированные решения, а руководствуется лишь поверхностной информацией. * Dictatorship/Диктатура: Ни один индивид не имеет всех умений необходимых для управления; также власть развращает * Discrimination/Дискриминация: Концентрация на неуместных особенностях усиливает экономическую неэффективность и социальную напряжённость * Dogmatic religion/Догма: Догма подавляет индивидуальное мышление и тормозит прогресс * Intolerance/Нетерпимость: Настаивание на изменении нежелательных-но-безопасных особенностей других людей влечёт усиление напряжённости и также является бесконечной задачей * Monopoly/Монополия: Без соперничества большинство эффектов свободного рынка не работают, и частная компания не имеет стимула действовать честно * Plurality voting system/Система голосования на основе большинства: Политика при голосовании на основе большинства вырождается в две полярно-противоположные партии, результатом чего является подавление других политических воззрений * Popularity contest/Соревнование в популярности: Популярность становится самодостаточной величиной и не сопоставима ни с каким другими параметрами или достоинствами * Racial segregation/Сегрегация: Разделение по равноправию весьма редко, если вообще существует; ведёт к напряжённости * Single-party system/Однопартийная система: Без избирательного соревнования партия не имеет побуждения управлять честно * Totalitarianism/Тоталитаризм: Подавление индивидуальности ведёт к напряжённости, вдобавок одобренный способ жизни никогда ещё не был годен для всех * Victimless crime/Преступление без жертв: Подавление безопасного поведения создаёт субкультуру людей, постоянно-живущих-по-другим-законам, для которых эта правовая система является врагом * Witch hunt/Охота на ведьм: Легко отыскать козла отпущения, но если проблема никогда не решается в действительности, результатом будет являться поиск всё новых и новых козлов отпущения * Year Zero/Нулевой Год: Социальное изменение является долгим процессом, ускорение его влечёт катастрофу Шуточные * Public Morozov/Паблик Морозов: Класс-потомок, созданный в соответствии с этим антипаттерном, выдает по запросу все данные класса-предка, независимо от степени их сокрытия. Название данного анти-паттерна — это каламбур, основанный на созвучии ключевого слова public (паблик), часто означающего открытый доступ к методам и полям класса в объектно-ориентированных языках программирования, и имени пионера-героя Павлика Морозова, известного тем, что он выдал своего отца-кулака. |
Автор: mes 20.6.2009, 11:01 |
У него только название шуточное, а на самом деле это самый настоящий антипаттерн. |
Автор: atomicxp 20.6.2009, 16:43 | ||
Пока не важно как их идентифицировали, главное что они есть. Может потом подправлю классификацию, да и описания надо получше написать и ещё дописать. Но на первое время хватит, здесь главное видны названия, то есть есть от чего отталкиваться. |
Автор: atomicxp 20.6.2009, 18:06 | ||||||||||||
Абстрактная фабрика (Abstract Factory) Для начала краткий курс знакомства с абстрактной фабрикой. ![]()
Применяется в построение GUI (окна и кнопки), компьютерных играх и так далее. Изменённый пример из вики:
Вывод консоли:
|
Автор: atomicxp 20.6.2009, 21:35 | ||||||||
Когда поправляют мои определения, мне кажется, что остальные люди догматики (антишаблон проектировани: Dogmatic religion/Догма), но ведь эти определения даны вовсе не мною. Может быть я следую догмам, потому что сам являюсь догматиком с поправкой на то, что слепая вера в них не по мне, этим и объясняется желание объяснить, почему делают так, а не иначе. А вот ещё одно интересное мнение на обсуждаемые нами правила. Скорее всего они действительно существовали от сотворения нашей вселенной, если такое вообще было.
|
Автор: atomicxp 21.6.2009, 00:37 | ||||||||||||
Рассмотрим абстрактные фабрики более внимательно. Как известно любая система состоит из элементов, эти части называют элементарными. Именно с ними оперируют люди, когда собирают или пересобирают свои системы. Помимо этого, сами элементы могут состоять из элементов по некой другой классификации. Иными словами хотя для нас эти элементы уже не делятся на подэлементы и являются сборками, с другой стороны их можно рассматривать на более глубоком уровне. В данном случае речь об интерфейсах, обзор которых проведён выше. Были выделены интерфейсы с различным свойствами. Во-первых, методы включённые в них могут находится в различных секциях, открытой и защищённой, но наверное чаще всего в открытой. Во-вторых, в одном случае интерфейсам позволяли удалять объект на который они ссылаются, а в другом нет. Пока условно обзову один абстрактным, в нём запрещено пользоваться деструктором, а второй объектным, там это соответственно разрешено. abstract interface
object interface
пример использования:
Вывод консоли:
В примере из вики для построения абстрактной фабрики использовались объектные интерфейсы способные вызывать утечку памяти. Такой интерфейс вывел бы:
Вместо:
Кстати, насчёт утечек памяти и всего прочего. В источниках информации посвящённых C++ этому уделяется огромное значение, что не совсем понятно. Не проще ли тупо использовать готовые реализованные шаблоны проектирования, которые гарантированно не вызовут утечек, чем каждый раз надоедать программистам со всякой ерундой. Следующий вопрос на повестке дня о том, что уже сама по себе абстрактная фабрика является не хилым извращением. Если же ещё попытаться применить в ней смешанные классы, то она может вырасти в непонятного монстра и перестанет опознаваться. Таким образом пока буду рассматривать чисто абстрактную фабрику, состоящую из идеальных элементов. Как видно, абстрактная фабрика состоит из абстрактных продуктов и самой абстрактной фабрики. И поскольку она применяет фундаментальный шаблон проектирования - интерфейс, помимо этого имеются классы конкретных продуктов и фабрик. Каждый продукт в абстрактной фабрике представлен его интерфейсом, причём создание конкретных продуктов перепоручается конкретным фабрикам. Так же стоит отметить, что в текущем примере из вики, создание происходило при получении объекта продукта посредством интерфейса, и после использования удаление делали вручную. А теперь представим, что программист не удалил объекты. И правда, он не обязан знать тонкости реализации (одно из правил книги «Совершенный код»). Причём программист ведь даже не видит, что объект создаётся, он видит только открытую часть, а она называется получить - get, а не создать - create. Следовательно текущая реализация абстрактной фабрики уже требует исправления по нескольким пунктам. |
Автор: mes 21.6.2009, 11:38 | ||
Не понял откуда Вы взяли get, когда даже на приведенной Вами схеме методы называются Create ![]() |
Автор: atomicxp 21.6.2009, 12:35 | ||
Из приведённого кода, откуда ещё, а у Александреску это называется Make. Даже не знаю, стоит ли помимо вики ещё его пример приводить, уж он то извратился по максимуму со своими шаблонами. |
Автор: mes 21.6.2009, 14:29 |
getNew.. и get .. не одно и то же. К тому же никто не обязывает именовать функции как в примере и ничто не мешает подобрать более подохдящие названия для интерфейса. |
Автор: atomicxp 21.6.2009, 14:40 | ||
Так и CreateProductA() и CreateProductB() не одно и тоже с Create
Лучше скажи как ты лично оцениваешь эффективность использования абстрактной фабрики в реальных примерах. |
Автор: mes 22.6.2009, 09:24 | ||
положительно ![]() |
Автор: azesmcar 22.6.2009, 09:28 | ||||
Фабрика и абстрактная фабрика очень красиво могут быть использованы с другими паттернами. Command например. Я использовал фабрику комманд в реализации RPC.
можно возвращать boost::shared_ptr чтобы избежать надобности очищать память. Ну и так далее... |
Автор: Sajra 22.6.2009, 20:59 |
Кто знает как на С++ реализировать патерн Proxy c умной ссылкой???? |
Автор: Леопольд 22.6.2009, 21:14 | ||
Зачем умная? Proxy служит так же и контейнером или она контролирует доступ? Всё зависит от специфики, я думаю... Я привык думать об умной ссылке как о чём-то, что автоматически заботиться о памяти. Т.е. вероятнее всего используется подсчёт ссылок. При разрушении последней, разрушается объект. И у меня поэтому такая стереотипная "умная" ссылка не очень сочетается с прокси. Или это не проки а надстройка над умной ссылкой, которую можно подключать динамически... хм? |
Автор: Lazin 22.6.2009, 21:45 | ||
какие тут все умные, даже неловко писать в этом умном трэде ![]() Добавлено через 6 минут и 29 секунд
что-то мне подсказывает, что для этого нужны 3 класса, причем один из них - смарт-поинтер, а другой - прокси ![]() |
Автор: atomicxp 22.6.2009, 22:06 |
Ты выражаешь общую мысль, вероятно от этого тема столь непопулярна. |
Автор: Sajra 22.6.2009, 22:10 |
Леопольд, у меня именно такое задание было! Народ ОЧЕНЬ нужен код...просто я так и не поняла нормально этой темы....мы ее разбирали минут 15.....книг нормальный нету.....НУ ПОЖАЛУЙСТА!!!!!! ![]() ![]() ![]() ![]() ![]() |
Автор: mes 23.6.2009, 00:33 |
Sajra, не флейми. Если есть свой вопрос открой новую тему. |
Автор: Леопольд 23.6.2009, 17:31 | ||
Книги есть. Рекомендую почитать классику GoF "Паттерны проектирования" http://www.rsdn.ru/res/book/oo/design_patterns.xml |
Автор: Леопольд 23.6.2009, 18:24 |
По моему, самое главное - разделяй и влавстуй. Используя любые, какие можешь придумать объекты/абстракции, но так, что бы каждый из них предназначается только для чего-то одного, что уже не имеет смысла разделять, и заставь эти объекты взаимодействовать друг с другом так, что бы достичь определённой цели. А если надо динамически поменять поведение системы, замени некоторые ключевые объекты на другие. Как правило, такие системы проще поддерживать и развивать, потому что надо добавить/заменить только некоторые объекты в системе и получишь новую функциональность... Я вот и говорю, изучить очень хорошо, но без свободы мысли, понять паттерны проектировани нельзя. Можно только использовать чужие и быть ими ограниченным. Конечно, придумать что-то новое не так просто. Но если понимать идеи так как будто ты их сам придумал, тогда можно постичь их истинный смысл. ![]() |
Автор: Леопольд 24.6.2009, 08:32 |
Предалагю пофилосовствовать. Философия - мать всех наук. Когда полезна "абстрактная фабрика"? Что-бы создавать.заменять некоторые части объекта динамически, можно использовать "абстрактную фабрику". Динамически заменив её на другую, получам возможность создать объект из других зап.частей. А если нам надо придумать новую запчасть, то можно просто написать её (с наследованием общего интерфейса) и фабрику, которая её создаёт при этом менять существующий код не надо (если интерфейсы прописаны достаточно полно). По моему, это очень актуально для больших проектов. Если паттерн используется правильно, то это может в десятки раз ускорить работу при поддержке/апдейте. Относительно интерфейса. Мне кажется, что интерфейс надо сужать путём разбиения на "неделимые единицы". Под "неделимыми единицами" я подразумеваю те интерфейсы, которые не имеет смысла делить дальше. Например, автомобиль состоит из зап.частей. - колёса, мотор, корпус... Однако речь идёт об интерфейсе, и по моему, автомобиль не должен иметь что-то от интерфейса колеса, двигателя, корпуса... (предположим что они нужны ![]() По моему, было бы неплохо пофилосовствовать над каждым описываемым паттерном. На мой взгляд, в целя изучения, это даже полезнее , чем реализовать паттерны на С++, хотя бы потому, что эти реализации не объясняют зачем тот или иной паттерн может пригодится. |
Автор: mes 24.6.2009, 08:53 | ||||||
Это плохой тон делегировать колесам команды автомобиля, он должен управлять ими. Но интерфейс автомобиля, может предоставлять интерфейс руля. ![]()
Это вообще лишнее.
Для этого достаточно обычной (не-абстрактной) фабрики. ![]() |
Автор: Леопольд 24.6.2009, 08:59 | ||||||||||||||||
Не согласен! ![]() Идеализировать что-то одно нельзя. Идолопоклонники как правило не могут мыслить гибко. Т.е. "выходить за рамки"...
Бесспорно. Руль для делегации подходит гораздо лучше потому что это руль. ![]()
Т.е. я имел ввиду, что, например, для замены руля на спортивный, можно сменить фабрику, "выпускающую" рули. При этом метод, который создает рули, переписывать/дописывать не надо. Насколько я помню, "абстрактная фабрика" это на самом деле семейство фабрик (с общим интерфейсом, думаю, не обязательно с одним). Т.е. вызов Create делегируется через интерфейс. Уверен, можно придумать другой способ динамически заменить фабрику.
Я пытался "привязаться" к чему то. По моему, так понятнее, зачем может понадобиться "абстрактная фабрика" И, пожалуйста, побольше философии. ![]() |
Автор: mes 24.6.2009, 09:43 | ||||||
Комментарий "это лишнее" я добавил, потому что на мой взгляд процитированная часть высказывания уводила от сути в сторону. Т.е была не просто лишней, а мешающей для понимания.
Ага.
Не понял смысла фразы. Какая разница как менять ? главное что есть возможность заменить ![]() |
Автор: Леопольд 24.6.2009, 12:06 | ||||||||
Это был комментарий к комментарию ![]() Мне очень интересно Ваше мнение о предназначении "абстракной фабрики". Не могли бы Вы его "озвучить"? Как известно, сколько людей, столько и мнений. Хотелось бы взглянуть вашими глазами. |
Автор: mes 24.6.2009, 13:08 | ||
Предназначение фабрики : независимость клиента от процесса создания продукта, а также инкапсуляция деталей этого процесса. Предназначение абстрактной фабрики : к вышеназванному добавляется также независимость от конкретной фабрики. |
Автор: Леопольд 24.6.2009, 13:13 | ||||||||||
Хотя, и правда лишнее, только мешает, удалил. Добавлено через 7 минут и 13 секунд
Я видимо неправильно выразился. Хотелось бы какой-то, пусть абстрактный, пример использования. Куда её можно прикрутить. и каие выгоды от этого поиметь. ![]() |
Автор: mes 24.6.2009, 14:23 | ||
Фабрика : создание "героев" для игры. A. Фабрика : плагин по созданию "героев" для игры. |
Автор: Леопольд 24.6.2009, 16:15 | ||||
У меня сразу появилось два вопроса. 1. Я считаю что небольшая потеря производительности ничто по сравнению с лёгкостью поддержки, дебага и дальнейшего развития хорошо спроектированной системы. Но предположим ![]() ![]() ![]() 2. Зачем "игре в героев" ![]() ![]() |
Автор: mes 24.6.2009, 16:24 |
наверно я неудачно подобрал слово "Hero" - имел ввиду в значении "персонаж". Фабрика нужна для того, чтоб эпизод игры не зависил от конкретных персонажей. Ну а ввиде плагина, чтоб можно было (например также стороннему производителю) создать другой мод. ![]() |
Автор: Леопольд 24.6.2009, 16:39 | ||||
А это как? ![]()
Как именно она это делает? Я не понимаю!!! ![]() Ещёб' 20 строчек про них. ![]() |
Автор: azesmcar 24.6.2009, 16:43 | ||
Леопольд Почитайте GoF, там есть описание абстрактной фабрики и конкретный пример ее применения. Кажется на лабиринте пример. Добавлено через 2 минуты и 3 секунды Скопировал из GoF. Известные применения шаблона проектирования "Абстрактная фабрика"
|
Автор: Леопольд 24.6.2009, 16:56 | ||
Я читал ![]() ![]() ![]() ![]() |
Автор: azesmcar 24.6.2009, 17:00 | ||
Я не говорю что не читал, я говорю где есть пример. Перефразирую, посмотрите в GoF.
Бывает и такое, но тут я что-то не заметил проблем понимания. Вроде все понятно. Насчет героев - я думаю автор идеи изложет лучше. |
Автор: mes 24.6.2009, 17:17 | ||
Например игра Pacman, тогда возможные персонажи : 1 . Колобок и демоны - классический 2. Снегурочка и снеговики - новогодний 3. Облачко и Тучи - небесный ![]() Т.е. один и тот же эпизод можно поиграть в различной обстановке. (Фабрика может поставлять не только персонажи игры, но и другие объекты сцены, в зависимости от требовани разработчиков) |
Автор: Леопольд 24.6.2009, 17:46 | ||
Отлично. Есть понимание что она делает. Но как именно она это делает, я не понимаю ![]() Добавлено @ 17:49
Я тоже. Яж' и говорю что я про это слышал (и местами читал)... ![]() Т.е. автор идеи про героев расскажет лучше? ![]() |
Автор: atomicxp 24.6.2009, 18:30 |
Предположим, что интерфейс это некий многоконтактный переключатель (multicontact switch) между объектами (здесь ещё можно подумать над темой классов с полностью статическими членами). Таким образом абстрактная фабрика будет комбинированием нескольких таких переключателей. Вот на мой взгляд картинка позволяющая объяснить принцип работы.![]() Каждый контакт ведёт к какому-то конкретному продукту, их количество определяется числом этажей, а массив тех что расположены одни над другими можно считать конкретной фабрикой. Абстрактные фабрики нужны чтобы массово менять продукты, на которые ссылаемся. Была высказана идея использования всего этого в виде плагинов. Сами плагины с помощью интерфейсов заключают контракты, что позволяет им быть независимыми. Следовательно, техника плагинов это не абстрактная фабрика. Но ведь как уже было сказано, абстрактные фабрики это массовые переключатели между объектами продуктов. Однако даже не комбинируясь, интерфейсы способны переключаться. Вероятно абстрактные фабрики нужны для массовых параллельных, то есть не пересекающихся переключений. Вопрос в другом, можно ли обойтись без них, надо ли их использовать, но это уже зависит от разработчиков. Нам просто дали способ, которым мы можем воспользоваться, и который отличим от других. |
Автор: atomicxp 24.6.2009, 19:01 |
Observer/Наблюдатель, Dependents, Publish-Subscribe, Event listener (GoF)![]() Определяет зависимость типа «один ко многим» между объектами таким образом, что при изменении состояния одного объекта все зависящие от него оповещаются об этом событии. При реализации шаблона «наблюдатель» обычно используются следующие классы. * Observable — интерфейс, определяющий методы для добавления, удаления и оповещения наблюдателей. * Observer — интерфейс, с помощью которого наблюдаемый объект оповещает наблюдателей. * ConcreteObservable — конкретный класс, который реализует интерфейс Observable. * ConcreteObserver — конкретный класс, который реализует интерфейс Observer. Шаблон «наблюдатель» применяется в тех случаях, когда система обладает следующими свойствами: * существует, как минимум, один объект, рассылающий сообщения * имеется не менее одного получателя сообщений, причём их количество и состав могут изменяться во время работы приложения. Данный шаблон часто применяют в ситуациях, в которых отправителя сообщений не интересует, что делают с предоставленной им информацией получатели. |
Автор: mes 24.6.2009, 20:00 | ||
Вот условный заготовок , надеюсь станет понятнее ![]()
|
Автор: Леопольд 24.6.2009, 21:22 | ||||
Мне всё было понятно из самого первого поста про игру с героями. Просто я люблю намекать. ![]() Я предлагал пофилосовствовать и совсем не использовать С++ для выражения мыслей. Потому что словами, в данном случае, описать сложнее. Но в результате придёт полное понимание и к тому, кто первый раз услышал про паттерны проектирования. Если, конечно, объяснено достаточно подробно и доступно. Добавлено @ 21:29
Статические методы С++ не могут быть виртуальными. Можно конечно использовать таблицу указателей на функции, но зачем тогда вообще нужны классы если обходиться без встроенного полиморфизма С++? Можно, например, просто использовать пространство имен и обычные функции... |
Автор: mes 24.6.2009, 21:55 | ||
Про абстрактную фабрику имхо нечего филосоствовать, так как она не имеет собственной сущности, а представлена обобщением двух других паттернов : Фабрика и Интерфейс. |
Автор: Леопольд 25.6.2009, 06:33 | ||
Вот теперь мне кажется что мы её "разобрали"... Возьмёмся за "наблюдателя"? ![]() |
Автор: mes 25.6.2009, 10:50 |
Патерн Наблюдатель с технической точки зрения это разновидность регистрации делегируемого интерфейса для установления обратной связи, при которой полагается, что наблюдаемый не зависит от реакции наблюдателя, т.е интерфейс не возвращает (прямо или косвенно) результат вызова. |
Автор: Леопольд 25.6.2009, 10:58 | ||
Но наблюдатели зависят от наблюдаемого, что логично... Следовательно, это позволяет при изменениях некоего объекта (наблюдаемого) как-то реагировать всем зарегестрированным наблюдателям, например, синхронизировать состояния. Думаю можно "подписаться" на разные события. Насколько мне известно, этот паттерн часто используют в GUI библиотеках для обработки различных ивентов. Что-то ещё он может? |
Автор: mes 25.6.2009, 11:37 |
Наблюдатель может только наблюдать и подписываться (сам или кем то) на наблюдения (и соответсвенно отписываться от них). Остальное выходит за рамки наблюдателя ![]() |
Автор: Леопольд 25.6.2009, 17:12 | ||
В общем, "правильнее" было бы назвать этот паттерн "прирождённый стукач", потому что он больше ничего не может ![]() Получается он бесполезен сам по себе. Но в совокупности с другими паттернами он явно может принести пользу. Я например вижу что можно с его помощью оповещать всех подписчиков наблюдателя об изменении наблюдаемого. Т.е. наблюдатель + делегат (или прокси). Какие-то ещё комбинации? |
Автор: mes 25.6.2009, 17:29 | ||
не получается. ![]() суть не в том что один объект сообщает о своем состоянии, а в том что другой может получить эти сообщения. Объект наблюдатель может все что ему захочется, но эти действия не подпадают под паттерн наблюдатель.
наблюдатель (объект, а не паттерн) и является подписчиком. ![]() делегат фактически является подпатерном наблюдателя. Точнее сказать паттерн наблюдатель описывает одно из применений делегатов. Прокси прямого отношения к рассматриваемому патерну не имеет. |
Автор: Леопольд 25.6.2009, 19:08 |
Предлагаю приложить его к игре с героями. Предположим в игре есть ресурсы, за счёт которых можно производить новых героев. Предположим, что эти ресурсы представляют из себя класс. Количество ресурсов можно увеличивать. Также имеются фабрики(а) героев. Есть заданная пользователем очередь "создания" героев. Разумно ли применить паттерн "наблюдатель" для того что-бы оповещать очередь создания о том что ресурсов достаточно для создания следующего в очереди героя? |