![]() |
Форум сайта insidecpp.ru.
Вы не вошли.
В статье "Шаблон проектирования "Одиночка" и "Закон Деметры" я рассмотрел вопрос о нарушении шаблоном "Одиночка" "Закона Деметры для функций и методов". Там я предложил использовать свободную функцию в пространстве имён "одиночки" для сокрытия получения доступа к его экземпляру. Тем самым, мы дублируем функции-члены "одиночки" свободными функциями, которые лишь перенаправляют вызов.
Другой, рекомендуемый приём - использовать класс-оболочку над "одиночкой". Но от дублирования мы не избавляемся и в этом случае. Однако данный приём показывает нам путь к решению. С точки зрения пользователя мы работаем не с одним экземпляром "одиночки", но семантически все экземпляры разделяют одно состояние. Это и есть ключевой момент. Значит нам не нужно делать класс "одиночку", обеспечивающий единственность экземпляра и содержащий необходимые функции. Нам нужен класс, предоставляющий функции, которые работают с одними и теми же данными для всех экземпляров этого класса.
В С++ это делается объявлением данных-членов класса статическими.
Таким образом, мы получаем класс, экземпляры которого разделяют одно состояние. Такй шаблон проектирования известен, хотя мало овещён в литературе (я нашёл лишь одно упоминание). Называется он "Monostate", то есть имеющий одно состояние. В один момент времени все экземпляры имеют одно состиояние или значение своих данных, то есть какбы "однозначны".
Мы рассмотрели ещё один способ реализации "одиночки". Но вам решать быть вашим классам "одинокими" или "однозначными".
А какое ваше мнение, коллеги?
Неактивен
addword написал:
Мы рассмотрели ещё один способ реализации "одиночки". Но вам решать быть вашим классам "одинокими" или "однозначными".
Если это - цитата, то неплохо было бы указать источник.
У реализации через статические поля есть ряд недостатков. Один из них : если инициализация статических полей не может зависеть от других статических полей, потому что порядок инициализации статических объектов в разных единицах трансляции не определен.
В этом случае остается только дублировать функции. А это ИМХО 1) геморой 2) ущерб в понятливости, либо засовывать ее в неймспейс и явно его указывать при вызове 3) Это обман закона, потому что все равно в итоге происходит то же самое.
Я бы т.н. Закон Деметры переименовал бы в Правило Деметры и для синглетонов сделал бы приятное исключение. =)
Неактивен
Это не цитата. С чего это Вы взяли?
По поводу применения пространства имён. Не согласен что это обман "Закона Деметры". Мы скрываем знание об объекте одиночке от тех, кто не должен этого знать. Ваши слова "..всё равно в итоге происходит то же самое." верны с точки зрения выполнения, но причём здесь архитектура?
А насчёт статических полей, инициализация которых зависят друг от друга, то это и есть настоящий геморрой. Этого нужно избегать всегда.
Неактивен
addword написал:
Это не цитата. С чего это Вы взяли?
По стилю процитированного мной предложения показалось, особенно "мы рассмотрели... ".
addword написал:
По поводу применения пространства имён. Не согласен что это обман "Закона Деметры". Мы скрываем знание об объекте одиночке от тех, кто не должен этого знать. Ваши слова "..всё равно в итоге происходит то же самое." верны с точки зрения выполнения, но причём здесь архитектура?
Верно... Но смысл закона Деметры в том, чтобы сделать связность элементов кода яснее и нагляднее, чтобы в программе было как можно меньше мест аля "Да где же находится определение этого левого класса к которому относится эта глобальная переменная?!!!". Да. Мы скрыли использование синглтона за методом, но связность от этого ни уменьшилась, ни стала нагляднее. Мы просто используем в коде имя функции вместо имени класса. И то и то - это просто сущности из одной и той же области видимости. Мне не видны плюсы вызова какой-то функции, за которой скрывается использование синглтона, вместо обращения к синглтону напрямую. Разве что.... элегантность? Зато скрывается факт использования синглтона.... А всегда ли это хорошо? А что если захочется заполучить ссылку на объект, который выдает GetInstance()?
addword написал:
А насчёт статических полей, инициализация которых зависят друг от друга, то это и есть настоящий геморрой. Этого нужно избегать всегда.
Именно! Поэтому, если нам необходимо реализовать две сущности, у которых инициализация первой зависит от второй, и которые должны существовать в единственном экземпляре, данный метод со статическими полями плох. Об этом и была речь. Правда, требование, возможно, сильно экзотическое...
Неактивен
Напомню:
В применении к объектно-ориентированному програмированию, "Закон Деметры" более точно называют "Закон Деметры для функций и методов" ("Law of Demeter for Functions/Methods” (LoD-F)).
Формально он выражается в том, что метод М объекта О может вызывать только методы следующих объектов:
1. Самого объекта О
2. Объектов, являющихя параметрами метода М
3. Любых объектов, созданных/инстанциированных внутри метода М
4. Объектов, являющихся непосредственными компонентами объекта О
И более ничего.
Причём здесь "связность"? Что Вы имеете в виду под "связностью элементов"?
Если вы имели в виду cohesion, то это относится к одному элементу(модулю) а не к группе элементов.
"Связность модуля (cohesion) – внутренняя характеристика модуля, характеризующая меру прочности соединения функциональных и информационных объектов внутри одного модуля. Связность модуля характеризует степень его «плотности», степень зависимости его частей и направленности на решение определенной задачи."
По-моему разумению смысл "Закону Деметры" в разделении обязанностей. Одна из его упрощённых формулировок - "Не разговаривай с незнакомцами".
Наделяя одну сущность знанием о статической природе другой, мы получаем "дырявую абстракцию".
Зачем одному объекту знать о том, что другой объект, которому он поручает какую-то работу, имеет только один экземпляр? Что это даёт с точки зрения выполнения полезной работы?
Зачем нужно "заполучать ссылку на объект, который выдаёт GetInstance()"? А может быть, ещё хуже, "заполучить" указатель на него?
Неактивен
addword написал:
Причём здесь "связность"? Что Вы имеете в виду под "связностью элементов"?
Я имел ввиду степень зависимости одних частей кода от других. В частности от "незнакомцев".
addword написал:
Наделяя одну сущность знанием о статической природе другой, мы получаем "дырявую абстракцию".
Это верно...
addword написал:
Зачем одному объекту знать о том, что другой объект, которому он поручает какую-то работу, имеет только один экземпляр? ... Зачем нужно "заполучать ссылку на объект, который выдаёт GetInstance()"?
Может быть и незачем...
Допускаю, что идея, может быть, и неплоха, но я бы хорошо подумал, прежде чем наворачивать набор методов над синглтоном. В большом проекте и без того хватает уровней косвенности и прочих заморочек. Чтобы сказать что-то более, надо попробовать этот подход на деле применить.
Неактивен
Хех, я поэтому и предлагаю не использовать Singleton, а использовать Monostate.
В этом случае клиент всегда инстанциирует новый объект ничего не зная о его "одноэкземплярной" сущности. А прямое обращение к инстанционированномому объекту не противоречит "Закону Деметры".
Отредактированно addword (2008-12-16 15:27:50)
Неактивен
addword
Ага. Только в тех случаях, когда поля требуют сложной инициализации, моностейт не так удобен, как синглтон. Например, если в моностейте статическим полем является вектор строк, который вначале выполнения нужно единожды прочитать из файла.
Неактивен
addword написал:
Зачем нужно "заполучать ссылку на объект, который выдаёт GetInstance()"? А может быть, ещё хуже, "заполучить" указатель на него?
MyCout::GetInstance() << "This is"; MyCout::GetInstance() << " not very"; MyCout::GetInstance() << " nice";
Либо
MyCout& mcout = MyCout::GetInstance(); mcout << "This is "; mcout << "more" mcout << "better."
Неактивен
Я вижу Вы не поняли что такое "Monostate". Отвечу в вашем стиле.
MyCout mcout; mcout << "Is it"; mcout << " something that"; mcout << " is worse?";
Отредактированно addword (2008-12-24 20:39:54)
Неактивен
addword написал:
Я вижу Вы не поняли что такое "Monostate"
Понял. Я просто ответил на конкретный вопрос, который процитировал.
Неактивен
| Статистика |
|
|