Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Dependency Injection, маловато инфы в рунете 
:(
    Опции темы
SABROG
  Дата 12.8.2010, 21:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Пытаюсь сделать "правильный" дизайн приложения. Есть классы типа Settings, DownloadManager, ScriptManager, JobManager.
И 3 класса должны иметь доступ к Settings, чтобы читать и писать свои данные. Напрашивается синглтон, но мы знаем, что это антипаттерн и поэтому он быстро "распрашивается" обратно. Альтернатива - передача указателя на Settings в конструктор каждого объекта (или через метод setSettings, что менее рекомендуемо). По сути советуют использовать Dependency Injection / Inversion Of Control (IoC) (пока разницы не понял, говорят, что одно частный случай другого). Сам паттерн не ограничивается передачей указателя на экземпляр класса, это должен быть указатель на интерфейс для конкретного класса типа ISettings, чтобы жестко не привязывать объекты друг к другу (забыл как называется это принцип ООП). Собственно на этой стадии реализация паттерна не идеальна (уже не помню почему), поэтому предлагают использовать так называемый контейнер (DI Container). Это разновидность шаблона Service Locator'а, где регистрируется связка КлассИнтерфейса=КонкретныйКласс. Обычно эти контейнеры настолько наворочены, что их выделяют в отдельные фреймворки и библиотеки. Собственно это то к чему я пришел убегая от сиглтона.

Почему в рунете так мало информации о паттерне Dependency Injection? А в англоязычных ресурсах информация представлена на 90% с примерами на Java. Я понимаю, что шаблон придумали именно разработчики Java, но неужели проблемы не существует на C++, что почти не реально найти примеры и классы? Что используете в разработке вместо Одиночек?


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
boostcoder
Дата 12.8.2010, 22:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



я бы предпочел синглтон. хоть это и антипаттерн, но иногда без него никуда.
второй вариант - передавать ссылку на Settings. чтоб не привязываться к типу, тип ссылки можно передать как шаблонный тип. ну или интерфейс(как вы и писали).

Это сообщение отредактировал(а) boostcoder - 12.8.2010, 22:55
PM WWW   Вверх
JackYF
Дата 12.8.2010, 23:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Передаю, грубо говоря, shared_ptr< [const] Settings > в конструктор. Собственно, не очень понял, что такое Dependency Injection и чем оно лучше даже того же синглтона.


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
djamshud
Дата 12.8.2010, 23:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пердупержденный
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 23.11.2009

Репутация: 8
Всего: 39



Предложу анти в кубе не-паттерн: глобальный объект сеттингс. У вас (не теоретически, а практически!) может быть одновременно несколько наборов настроек, параллельно живущих и использующихся во время работы программы? Нет? Тогда плюньте на теоретика Александреску и решайте свою задачу, а не высосанную из пальца проблему.

Добавлено через 37 секунд
Впрочем и синглтон в равной степени подходит...


--------------------
'Cuz I never walk away from what I know is right
Alice Cooper - Freedom
PM   Вверх
SABROG
Дата 13.8.2010, 00:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(boostcoder @  12.8.2010,  22:55 Найти цитируемый пост)
я бы предпочел синглтон

Цитата(JackYF @  12.8.2010,  23:14 Найти цитируемый пост)
чем оно лучше даже того же синглтона.

Цитата(djamshud @  12.8.2010,  23:32 Найти цитируемый пост)
Впрочем и синглтон в равной степени подходит... 


Лучше тем, что не singleton с его недостатками. В принципе не сложно писать такие цепочки:

Код

int main(int argc, char* argv[])
{
    ServiceLocator loc;
    A a(&loc);
    return 0;
}
...
void A::A(ServiceLocator* loc)
{
    m_locator = loc;
}
...
void A::foo()
{
    C c = new C(m_locator);
}


Другое дело, что вариант не идеален,  а как работают DI Container'ы для C++ я пока не до конца разобрался.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Любитель
Дата 13.8.2010, 01:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 24
Всего: 92



Во-первых, с иок-ом, как таковым, всё просто - не делай зависимости класса A от класса Settings. Делай интерфейс ISettings и работай с ним. 

Но, во-вторых, это неудобно - т. к. придётся передавать указатель на объект настроек. "Инъекция" возможна только в том случае, если все объекты мы получаем через DI-контейнер. Т. е. в итоге мы:
1. Регистрируем (где-нить при старте приложения) маппинг: ISettings -> DbSettings, или XmlSettings, или IniSettings (да, вообще логично что Settings - это чисто объект данных, а методы load/save/etc. в SettingsManager-е каком-нибудь, ну да ладно).
2. Добавляем параметр типа ISettings в конструктор нашего класса A (инъекция в конструктор - самая простейшая и достаточно популярная).
3. Вместо создания объекта класса A пишем container.Resolve<A>().

В общем-то всё красиво. У DbSettings у нас будет IDbConnection (я условно), который тоже автоматом зарезольвится на что надо - и т. д. Более того, любой DI-контейнер на практике действительно является и сервис локатором ("чистый" DI-контейнер должен производить только "инъекции", а создание/получение объектов - не его дело, но на практике такого не бывает). А это значит, что мы также можем регулировать время жизни объектов и пр.

Теперь проблемы. Любой настоящий DI-контейнер реализуется с использованием рефлекшена. Именно поэтому это (в основном) ява/шарп. В чистом С++ "правильного" DI вообще не может быть. С учёток оберток, предоставляющих метаданные (как в том ж Qt) - в принципе сделать вомзожно, но я не встречал готовых реализаций.

В случае С++ на мой взгляд есть 2 варианта:
1. Если нужна действительна абстракция - простейшая фабрика, без каких либо наворотов.
2. Если нет - то синглтон smile

Более того - даже в случае явы/шарпа я бы не стал городить иерархии классов/интерфейсов и полную абстракцию, если это бы действительно не было бы нужно.


--------------------
PM MAIL ICQ Skype   Вверх
SABROG
Дата 13.8.2010, 07:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(Любитель @  13.8.2010,  01:43 Найти цитируемый пост)
С учёток оберток, предоставляющих метаданные (как в том ж Qt) - в принципе сделать вомзожно, но я не встречал готовых реализаций.

Они есть:

QNimbleContainer
QtIocContainer

Другое дело, что они жестко привязаны к мета-объектной системе и как следствие любой класс должен наследовать QObject. К тому же не хотелось бы использовать сторонние библиотеки/фреймворки ради того, чтобы просто уйти от синглтона.


Цитата(Любитель @  13.8.2010,  01:43 Найти цитируемый пост)
Если нужна действительна абстракция - простейшая фабрика, без каких либо наворотов.

То есть реализовать Service Locator через фабрику и передавать указатель на IServiceLocator через конструктор в каждый объект, типа этого?
Цитата(Любитель @  13.8.2010,  01:43 Найти цитируемый пост)
Если нет - то синглтон  smile 

Эхх, если начать реализацию синглтона, то помимо идеологических проблем существует и физиологическая - проблема с потоко-безопасностью. Чтобы его сделать потоко-безопасным придется прибегнуть к double checked locking паттерну реализованному через атомарные операции, которых пока нет в C++, это значит надо использовать сторонние библиотеки, BOOST например (ну или начать использовать функции из C++0x)


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Любитель
Дата 13.8.2010, 09:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 24
Всего: 92



Цитата(SABROG @  13.8.2010,  07:19 Найти цитируемый пост)
QtIocContainer

Совсем не впечатлило. Всё делать через плагины - это жёстко.

Цитата(SABROG @  13.8.2010,  07:19 Найти цитируемый пост)
QNimbleContainer

Здесь уже гораздо лучше. Беглый просмотр блога говорит о том, что направление выбрано верное. Но.. насколько это production ready - уже другой вопрос (всё-таки пока похоже больше на грамотное увлечение).

Цитата(SABROG @  13.8.2010,  07:19 Найти цитируемый пост)
Другое дело, что они жестко привязаны к мета-объектной системе и как следствие любой класс должен наследовать QObject.

Ну.. так или иначе они будут расчитывать на некоторый базовый класс - для эмуляции рефлекшена (черех собственное хранилище метаданных). Ну или точнее так - в принципе базовый класс не обязательно, но на хранилище метаданных обязательно (ну плюс там ещё проблема универсальной передачи параметров появляется, решаемая в Qt через QVariant).

Цитата(SABROG @  13.8.2010,  07:19 Найти цитируемый пост)
То есть реализовать Service Locator через фабрику и передавать указатель на IServiceLocator через конструктор в каждый объект, типа этого?

Ну.. Service Locator реально нужен когда? Когда у нас накапливается много объектов, создаваемых через фабрики. И особенно, если при этом между ними есть какие-то связи. Т. е. по сути это централизованная фабрика. Т. е. в простых случаях достаточно обычных фабрик (per class). Далее - передавать указатель на IServiceLocator я бы не стал. Уж саму фабрику точно делал бы синглтоном, ну или просто статик поля/методы. Смысл абстрагировать абстракцию?

Цитата(SABROG @  13.8.2010,  07:19 Найти цитируемый пост)
Эхх, если начать реализацию синглтона, то помимо идеологических проблем существует и физиологическая - проблема с потоко-безопасностью.

Во-первых, в плане life scope в случае навороченных DI-контейнеров всегда есть опция синглетона. Наличие одного (и только одного) экземпляра класса в системе - не есть плохо. Плохо то, что мы жёстко зависимы от этого.

Во-вторых - будут ли проблемы с потоками, это зависит от конкретного кода объекта. И в большинстве случаев наиболее удачным решением будет просто использование TLS а не локи (по крайней мере уровень паралелизма будет гораздо выше). Любой уважающий себя компилятор это поддерживает, одним дефайном решается необходимость привязки к конкретному компилеру.


--------------------
PM MAIL ICQ Skype   Вверх
Earnest
Дата 13.8.2010, 10:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(Любитель @  13.8.2010,  10:39 Найти цитируемый пост)
 И в большинстве случаев наиболее удачным решением будет просто использование TLS а не локи 

TLS - это хороший выход только если каждый поток должен иметь свой экземпляр. А это вроде бы не так. Если система не очень сложная, может, не стоит парится с thread-safe синглетона. Т.е. доступ к данным действительно нужно синхронизировать.
А "double checked locking паттерн" реально нужен только, если возможны накладки при создании или уничтожении.


--------------------
...
PM   Вверх
Леопольд
Дата 13.8.2010, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(SABROG @  13.8.2010,  07:19 Найти цитируемый пост)
Чтобы его сделать потоко-безопасным придется прибегнуть к double checked locking паттерну реализованному через атомарные операции, которых пока нет в C++
Если я правильно понял настройки должны быть в одном инстансе, доступ к которому осуществляется из нескольких потоков. Как то можно гарантироваить безопастность доступа без какой-либо синхронизации? Ведь в любом случае придётся использовать какую-то блокировку, нет?


Это сообщение отредактировал(а) Леопольд - 13.8.2010, 10:20


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
Леопольд
Дата 13.8.2010, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(Earnest @  13.8.2010,  10:11 Найти цитируемый пост)
А "double checked locking паттерн" реально нужен только, если возможны накладки при создании или уничтожении. 
Цитата(SABROG @  13.8.2010,  07:19 Найти цитируемый пост)
придется прибегнуть к double checked locking
Может просто создать объект в статической памяти?



--------------------
вопросов больше чем ответов
PM MAIL   Вверх
Леопольд
Дата 13.8.2010, 11:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(SABROG @  13.8.2010,  07:19 Найти цитируемый пост)
придется прибегнуть к double checked locking паттерну реализованному через атомарные операции, которых пока нет в C++
Код
#include <boost/thread/mutex.hpp>

template<typename T>
struct Singleton{
    static T& instance(){
        if(!instance_){
            boost::mutex::scoped_lock lock(mutex_);
            if(!instance_)
                instance_ = new T();
        }
        return const_cast<T&>(*instance_);
    }
private:
    static volatile T* instance_;
    static boost::mutex mutex_;
};
template<typename T>
volatile T* Singleton<T>::instance_ = 0;
template<typename T>
boost::mutex Singleton<T>::mutex_;

Не пойму, зачем здесь атомарные операции? Любой поток будет залочен до тех пор, пока объект не будет полностью сконструирован.


Это сообщение отредактировал(а) Леопольд - 13.8.2010, 11:34


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
SABROG
Дата 13.8.2010, 11:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(Любитель @  13.8.2010,  09:39 Найти цитируемый пост)
ну или просто статик поля/методы

Цитата(Леопольд @  13.8.2010,  10:39 Найти цитируемый пост)
Может просто создать объект в статической памяти?

QtCreator для кода:

Код

Core::EditorManager::instance();


Использует разновидность синглтона Мейерса. Только если в оригинале он не потоко-безопасен, то у них подход хитрее.
Предполагается, что любое приложение изначально создается как single threaded, поэтому пока мы не наплодили других потоков предварительно происходит инициализация всех "синглтонов", например где-нибудь в main(). Сам вариант приблизительно выглядит так:

Код

// .h
class EditorManager
{
public:
    EditorManager()
    {
         m_instance = this;
    }
    static EditorManager* instance() {return m_instance;}
private:
    static EditorManager* m_instance;
};
...
// .cpp
static EditorManager::m_instance = 0;
...
// main.cpp
int main(int argc, char* argv[])
{
    (void)new EditorManager; // создание экземпляра одиночки
}



Недостатки такого подхода очевидны, но я пока склоняюсь к этому варианту, как наиболее простому и хоть частично потоко-безопасном по сравнению с таким вариантом, который без синхронизации потоков вообще не безопасен:
Код

    static GlobalClass *instance()
    {
        if (!s_instance)
          s_instance = new GlobalClass;
        return s_instance;
    }



Цитата(Любитель @  13.8.2010,  09:39 Найти цитируемый пост)
Смысл абстрагировать абстракцию?

Чтобы отвязаться от класса ServiceLocator, впихнуть тесты, при желании подсунуть "заглушку".

Цитата(Earnest @  13.8.2010,  10:11 Найти цитируемый пост)
Если система не очень сложная, может, не стоит парится с thread-safe синглетона. Т.е. доступ к данным действительно нужно синхронизировать.
А "double checked locking паттерн" реально нужен только, если возможны накладки при создании или уничтожении. 

Предположим я хочу научиться делать автомобили. Специалисты отправляют меня сначала научиться делать велосипеды. Когда я научусь их делать, то настанет очередь чего-то более сложного. То есть на данном этапе мне важно не быстрей что-либо написать, а понять как делать это правильно в будущем, когда такая необходимость настанет.

Цитата(Леопольд @  13.8.2010,  10:20 Найти цитируемый пост)
Как то можно гарантироваить безопастность доступа без какой-либо синхронизации? Ведь в любом случае придётся использовать какую-то блокировку, нет?

В случае заранее проинициализированного указателя проблем атомарного чтения самого указателя возникнуть не должно (по крайней мере на AI-32), а работу с данными на которые он указывает нужно синхронизировать, благо в Qt достаточно поток-безопасных классов и Qt сама берет на себя эту рутину. Тут конечно остается проблема с "висячим" объектом синглтона, который может быть даже и не используется нигде в коде (но это редкий случай, нафига его тогда вообще создавать).

Цитата(Леопольд @  13.8.2010,  11:22 Найти цитируемый пост)
Не пойму, зачем здесь атомарные операции? Любой поток будет залочен до тех пор, пока объект не будет полностью сконструирован.


Во первых мутекс блокирует работу всех остальных потоков, которые пытаются получить доступ к синглтону, а могли бы делать полезную работу. Если дальше копать, то там нужен второй мутекс, а потом в итоге и он не спасает, погугли на "Double Checked Locking Broken".

Как я уже упомянул нужен "безопасный" вариант шаблона Double Checked Locking, который реализован в функции boost::callonce(), вот пример нормального потоко-безопасного синглтона: http://www.boostcookbook.com/Recipe:/1235044

Но это мне не подходит, так как я пока не хочу тянуть boost, да еще и ради антипаттерна.

Это сообщение отредактировал(а) SABROG - 13.8.2010, 11:49


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Любитель
Дата 13.8.2010, 11:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 24
Всего: 92



Цитата(SABROG @  13.8.2010,  11:37 Найти цитируемый пост)
Недостатки такого подхода очевидны, но я пока склоняюсь к этому варианту, как наиболее простому и хоть частично потоко-безопасном по сравнению с таким вариантом, который без синхронизации потоков вообще не безопасен:

А, так ты ведёшь речь именно про создание инстанса. А я то думал про "небезпоасные" его методы. Если ты уверен в безопасности методов - то очевидно, что тут и обычные объекты синхронизации (т. е. обычная блокировка) подойдут:
Код

if (_instance)
  return _instance;

_mutex.lock();
if (!_instance)
  _instance = new MyClass;
_mutex.release();

return _instance;


Цитата(SABROG @  13.8.2010,  11:37 Найти цитируемый пост)
Чтобы отвязаться от класса ServiceLocator, впихнуть тесты, при желании подсунуть "заглушку".

Ну.. А создание сервис локатора кто-то ж будет делать? Потом будем это создание абстрагировать и т. д. Я не очень вижу в этом смысл. Заглушку на классы, занимающиеся "функционалом" - ок. Тесты - ок. Но зачем сервис-локатор абстрагировать? Единственный случай, который можно придумать - это желание использовать для него какой-т фреймворк и возможность переключение между разными фреймворками (не в процессе, а в перспективе проекта). Но.. это только если речь про достаточно нетривиальную реализацию.


--------------------
PM MAIL ICQ Skype   Вверх
SABROG
Дата 13.8.2010, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(Любитель @  13.8.2010,  11:48 Найти цитируемый пост)
(т. е. обычная блокировка) подойдут

Так это и есть тот самый "сломанный" вариант Double Checked Locking паттерна.

Цитата(Любитель @  13.8.2010,  11:48 Найти цитируемый пост)
Но зачем сервис-локатор абстрагировать? Единственный случай, который можно придумать - это желание использовать для него какой-т фреймворк и возможность переключение между разными фреймворками (не в процессе, а в перспективе проекта). Но.. это только если речь про достаточно нетривиальную реализацию.

Зачем-то разработчики Microsoft его используют (IServiceLocator + IServiceProvider). Видимо, чтобы конечный пользователь мог подставлять собственные фабрики. К тому же опять идет жесткая привязка к конкретной реализации:

user posted image


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Леопольд
Дата 13.8.2010, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(SABROG @  13.8.2010,  11:37 Найти цитируемый пост)
Во первых мутекс блокирует работу всех остальных потоков, которые пытаются получить доступ к синглтону, а могли бы делать полезную работу. Если дальше копать, то там нужен второй мутекс, а потом в итоге и он не спасает, погугли на "Double Checked Locking Broken".
Блокирует только если инстанс не создан и до тех пор, пока он не будет создан целиком, иначе просто возвращает указатель без блокировки.



--------------------
вопросов больше чем ответов
PM MAIL   Вверх
SABROG
Дата 13.8.2010, 12:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(Леопольд @  13.8.2010,  12:30 Найти цитируемый пост)
Блокирует только если инстанс не создан и до тех пор, пока он не будет создан целиком, иначе просто возвращает указатель без блокировки.

Фиг с ней с этой блокировкой, там причина в многократной инициализации одного и того же синглтона в разных потоках.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Леопольд
Дата 13.8.2010, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(SABROG @  13.8.2010,  12:45 Найти цитируемый пост)
там причина в многократной инициализации одного и того же синглтона в разных потоках.
Цитата(SABROG @  13.8.2010,  12:45 Найти цитируемый пост)
Блокирует ... до тех пор, пока он не будет создан целиком



Это сообщение отредактировал(а) Леопольд - 13.8.2010, 13:24


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
SABROG
Дата 13.8.2010, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(Леопольд @  13.8.2010,  13:23 Найти цитируемый пост)
Блокирует ... до тех пор, пока он не будет создан целиком

Это относится к одному потоку. Каждый поток будет создавать целиком по своей копии. На уровне компилятора тут нет синхронизации.

Не забывай и про такую ситуацию:

Код

m_instance = new MySingleton; 
// под объект выделяется память и указатель присваивается m_instance
// затем другой поток прерывает работу этого потока еще до того как он успеет вызвать конструктор
// другой поток видит, что указатель существует, т.е. объект создан и пытается с ним работать
// а объект синглтона не валиден по той простой причине, что конструктор еще не вызывался



--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
boostcoder
Дата 13.8.2010, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(SABROG @  13.8.2010,  11:37 Найти цитируемый пост)
в функции boost::callonce()

Цитата(SABROG @  13.8.2010,  11:37 Найти цитируемый пост)
Но это мне не подходит, так как я пока не хочу тянуть boost, да еще и ради антипаттерна.

ради call_once() boost тащить не надо. она есть во всех свежих версиях компиляторов.

Добавлено через 1 минуту и 56 секунд
SABROG, мешанина какая-то в теме..
в данный момент, как я понял, проблема в инициализации синглтона? или в чем?

Добавлено через 2 минуты и 40 секунд
Цитата(boostcoder @  13.8.2010,  13:34 Найти цитируемый пост)
она есть во всех свежих версиях компиляторов.

по моему, она есть даже в Qt.
PM WWW   Вверх
SABROG
Дата 13.8.2010, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(boostcoder @  13.8.2010,  13:34 Найти цитируемый пост)
она есть во всех свежих версиях компиляторов.

Она есть только в стандарте C++0x. Я конечно не консерватор, но стандарт еще не принят и хочется переносимости на старые компиляторы.

Цитата(boostcoder @  13.8.2010,  13:34 Найти цитируемый пост)
в данный момент, как я понял, проблема в инициализации синглтона? или в чем?

Сейчас мне интересно мнение насчет варианта без синглтона, варианта, который используется в нескольких проектах, которые я обнаружил через google/codesearch. То есть разновидность глобальных указателей:
Код

// .h
class EditorManager
{
public:
    EditorManager()
    {
         m_instance = this;
    }
    static EditorManager* instance() {return m_instance;}
private:
    static EditorManager* m_instance;
};
...
// .cpp
static EditorManager::m_instance = 0;
...
// main.cpp
int main(int argc, char* argv[])
{
    EditorManager em; // создание экземпляра одиночки
    doStuff();
    ...
}


Цитата(boostcoder @  13.8.2010,  13:34 Найти цитируемый пост)
по моему, она есть даже в Qt. 

Нету, я писал свою реализацию при помощи Дмитрия Вьюкова (специалиста по конкурентному программированию).


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Леопольд
Дата 13.8.2010, 14:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(SABROG @  13.8.2010,  13:31 Найти цитируемый пост)
// другой поток видит, что указатель существует, т.е. объект создан и пытается с ним работать
// а объект синглтона не валиден по той простой причине, что конструктор еще не вызывался
Спасибо. Упустил этот момент.

Добавлено @ 14:12
Цитата(SABROG @  13.8.2010,  13:46 Найти цитируемый пост)
Сейчас мне интересно мнение насчет варианта без синглтона, варианта, который используется в нескольких проектах, которые я обнаружил через google/codesearch. То есть разновидность глобальных указателей:
Хорошо сочетается с принципом KISS smile


Это сообщение отредактировал(а) Леопольд - 13.8.2010, 14:13


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
mes
Дата 13.8.2010, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(SABROG @  12.8.2010,  20:44 Найти цитируемый пост)
. Напрашивается синглтон, но мы знаем, что это антипаттерн и поэтому он быстро "распрашивается" обратно

не читал, темы, но для доступа к настройкам имхо уже есть _синглетон_ приложения , который можно использовать. (наследник QApp в вашем случае ) smile


--------------------
PM MAIL WWW   Вверх
SABROG
Дата 13.8.2010, 16:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(mes @  13.8.2010,  14:50 Найти цитируемый пост)
наследник QApp в вашем случае

Вопрос задавался в контексте языка C++, а не конкретного фреймворка. А так то варианты есть.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Леопольд
Дата 13.8.2010, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(SABROG @  13.8.2010,  13:31 Найти цитируемый пост)
// другой поток видит, что указатель существует, т.е. объект создан и пытается с ним работать
// а объект синглтона не валиден по той простой причине, что конструктор еще не вызывался
Код

#include <boost/thread/mutex.hpp>

template<typename T>
struct Singleton{
    static T& instance(){
        if(!instance_){
            boost::mutex::scoped_lock lock(mutex_);
            if(!instance_)
                instance_ = create_();
        }
        return const_cast<T&>(*instance_);
    }
private:
    static volatile T* instance_;
    static boost::mutex mutex_;

    typedef T* (*FPtr) ();
    typedef volatile FPtr VFPtr;
    static VFPtr create_;
    static T* creator(){
        return new T();
    }
};
template<typename T>
volatile T* Singleton<T>::instance_ = 0;
template<typename T>
boost::mutex Singleton<T>::mutex_;
template<typename T>
typename Singleton<T>::VFPtr Singleton<T>::create_ = &Singleton<T>::creator;
smile 

Это сообщение отредактировал(а) Леопольд - 13.8.2010, 16:34


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
mes
Дата 13.8.2010, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(SABROG @  13.8.2010,  15:20 Найти цитируемый пост)
Вопрос задавался в контексте языка C++, а не конкретного фреймворка. А так то варианты есть. 

1. суть не меняется... настройки это часть приложения, через него они и должны быть доступны..
2. синглетон не всегда антипаттерн. Антипаттерн  - применять синглетон без обдумывания.
дальнейшее зависит от задачи и фреймворка.


--------------------
PM MAIL WWW   Вверх
SABROG
Дата 13.8.2010, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(Леопольд @  13.8.2010,  16:33 Найти цитируемый пост)

Код

    static T* creator(){
        return new T();
    }


К сожалению не спасет от двух видов оптимизации. Одну делает компилятор, другую может делать линкер. Как получить гарантии того, что этих оптимизаций производиться не будет на всех известных компиляторах?

Как сказали бы Александреску с Мейерсом: "Game over. You lose." Почитай статью, чтобы не придумывать новых велосипедов.




--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Леопольд
Дата 13.8.2010, 18:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(SABROG @  13.8.2010,  18:25 Найти цитируемый пост)
К сожалению не спасет от двух видов оптимизации. Одну делает компилятор, другую может делать линкер. Как получить гарантии того, что этих оптимизаций производиться не будет на всех известных компиляторах?
volatile указатель на функцию, и вызов функции через этот указатель.
Александреску конечно умный мужик, но это не повод унывать...  smile 

Код
    typedef T* (*FPtr) ();
    typedef volatile FPtr VFPtr;
    static VFPtr create_;
    ...
    template<typename T>
    typename Singleton<T>::VFPtr Singleton<T>::create_ = &Singleton<T>::creator;
    ...
    instance_ = create_();


Если есть какие-то сомнения, то можно заменить на виртуальный вызов через указатель на базовый класс. Наследника определить в другой единице трансляции, на всякий случай.

Это сообщение отредактировал(а) Леопольд - 13.8.2010, 18:50


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
Леопольд
Дата 13.8.2010, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(SABROG @  13.8.2010,  18:25 Найти цитируемый пост)
Почитай статью
Читал, где-то год назад. Вот ещё интересная статься под авторством Александреску. http://www.drdobbs.com/184403766;jsessioni...HPSKH4ATMY32JVN



--------------------
вопросов больше чем ответов
PM MAIL   Вверх
SABROG
Дата 13.8.2010, 19:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Следом идет другая проблема - когерентность кеша. У каждого ядра/процессора своя копия данных памяти в кеше и когда один поток меняет данные (устанавливает указатель, инициализирует члены класса), то нужно об этом сообщать другим потокам, иначе у них останутся "старые" данные. То есть возникает необходимость добавлять барьеры памяти или использовать атомарные инструкции типа Acquire/Release, чтобы сообщать другим потокам, что чего-то изменилось и кеши нужно обновить. Стандартных механизмов сделать это в C++ нет. На данном этапе этот язык совершенно не подготовлен к конкурентному программированию. К счатью работа в этом направлении ведется и с новым стандартом мы получим полноценный набор атомарных методов.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Леопольд
Дата 13.8.2010, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(SABROG @  13.8.2010,  19:52 Найти цитируемый пост)
К счатью работа в этом направлении ведется и с новым стандартом мы получим полноценный набор атомарных методов. 
Когда ещё это будет...


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
mes
Дата 13.8.2010, 20:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(SABROG @  13.8.2010,  18:52 Найти цитируемый пост)
На данном этапе этот язык совершенно не подготовлен к конкурентному программированию

 smile smile


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 14.8.2010, 00:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



SABROG, ваша ситуация ясна.
но последующими вопросами, вы, похоже, пытаетесь всех загрузить? smile 
то, о чем вы мыслите - правильно. я бы сказал, через чур правильно. т.к. сложность на реализацию "правильного", переплевывает все адекватные времячасовые расходы.

Цитата(SABROG @  13.8.2010,  19:52 Найти цитируемый пост)
Следом идет другая проблема - когерентность кеша. У каждого ядра/процессора своя копия данных памяти в кеше и когда один поток меняет данные (устанавливает указатель, инициализирует члены класса), то нужно об этом сообщать другим потокам, иначе у них останутся "старые" данные.

в с++0х есть способы борьбы.

Цитата(SABROG @  13.8.2010,  19:52 Найти цитируемый пост)
Стандартных механизмов сделать это в C++ нет.

угу.

Цитата(SABROG @  13.8.2010,  19:52 Найти цитируемый пост)
На данном этапе этот язык совершенно не подготовлен к конкурентному программированию.

угу.
смотрите Go
Цитата(SABROG @  13.8.2010,  19:52 Найти цитируемый пост)
К счатью работа в этом направлении ведется и с новым стандартом мы получим полноценный набор атомарных методов.

угу. а вы только краски сгущаете. не забывайте о том, в каких годах, и для какого оборудования разрабатывался с++.

Это сообщение отредактировал(а) boostcoder - 14.8.2010, 00:27
PM WWW   Вверх
SABROG
Дата 14.8.2010, 08:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(boostcoder @  14.8.2010,  00:25 Найти цитируемый пост)
вы, похоже, пытаетесь всех загрузить?  smile 

Нет, просто объяснил свою позицию насчет синглтонов. Думаете мне хотелось вдаваться в детали проблемы? Это всего лишь ответы на ваши вопросы.

Цитата(boostcoder @  14.8.2010,  00:25 Найти цитируемый пост)
т.к. сложность на реализацию "правильного", переплевывает все адекватные времячасовые расходы.

Я думаю это тот случай, когда достаточно один раз сделать правильно и использовать в последующих проектах.

Цитата(boostcoder @  14.8.2010,  00:25 Найти цитируемый пост)
в с++0х есть способы борьбы.

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

Цитата(boostcoder @  14.8.2010,  00:25 Найти цитируемый пост)
угу. а вы только краски сгущаете. не забывайте о том, в каких годах, и для какого оборудования разрабатывался с++.

Самое смешное в том, что за последние 20 лет вышло такое количество разных языков программирования, где многих недостатков C++ просто нет. Когда у меня на компьютере по нескольку раз в неделю обновляется виртуальная машина Java я вижу насколько быстро этот язык развивается. Я не вижну какой-то активности по этому поводу со стороны разработчиков C++. А они вообще есть? Есть люди, которые пишут инструкцию (стандарт), а есть те, кто на основе неё пишет компилятор (ms, gcc, intel), и каждый делает это по своему разумению, да так, что производительность, устойчивость, переносимость программ с одним и тем же исходным кодом - разная.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Леопольд
Дата 14.8.2010, 08:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(SABROG @  14.8.2010,  08:24 Найти цитируемый пост)
Когда у меня на компьютере по нескольку раз в неделю обновляется виртуальная машина Java я вижу насколько быстро этот язык развивается.
Может это они баги правят.... smile


Это сообщение отредактировал(а) Леопольд - 14.8.2010, 09:08


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
SABROG
Дата 14.8.2010, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Почитал, что предложил JackYF, вроде тоже вариант не плохой. Как насчет такой реализации?

Код

class ISettings;
class ISettings
{
public:
    typedef QSharedPointer<ISettings> Ptr;
    ...
    virtual bool load() = 0;
    virtual bool save() = 0;
    virtual QVariant value(const QString& name) = 0;
};

class Settings : public ISettings
{
public:
    ...
    virtual bool load()
    {
        QFile file("settings.ini");
        ...
    }
    
    virtual QVariant value(const QString& name)
    {
        return data[name].value();
    }
};

class IDownloadManager
{
public:
    typedef QSharedPointer<IDownloadManager> Ptr;
    ...
    virtual bool connectToServer(const QString& host, const QString& port) = 0;
}

class DownloadManager : IDownloadManager
{
    ...
public:
    explicit DownloadManager(ISettings::Ptr settings) : m_settings(settings)
    {
    }

    ISettings::Ptr settings() const {return m_settings;}

    virtual bool connectToServer(const QString& host, const QString& port)
    {
        ...
    }

    void foo()
    {
        ...
        connectToServer(settings()->value("host").toString(), 
                        settings()->value("port").toString());
    }

private:
    ISettings::Ptr m_settings;
};

int main(int argc, char* argv[])
{
    ISettings::Ptr settings = ISettings::Ptr(new Settings);
    IDownloadManager::Ptr downloadManager 
                = IDownloadManager::Ptr(new DownloadManager(settings));
    ...
    return 0;
}



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

Это сообщение отредактировал(а) SABROG - 14.8.2010, 14:47


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
boostcoder
Дата 14.8.2010, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



ИМХО, операторы new в main() лишние. и смартпоинтер в этом случае не нужен.
PM WWW   Вверх
SABROG
Дата 14.8.2010, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(boostcoder @  14.8.2010,  14:38 Найти цитируемый пост)
ИМХО, операторы new в main() лишние. и смартпоинтер в этом случае не нужен. 

Как бы предполагается, что эта реализация может работать не только в main(), но и в каком нибудь MainWindow. Без new смарт поинтеры вроде как работать не могут. Все-таки удалять в деструкторе локальную переменную через delete - чревато.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
boostcoder
Дата 14.8.2010, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(SABROG @  14.8.2010,  14:41 Найти цитируемый пост)
Без new смарт поинтеры вроде как работать не могут. Все-таки удалять в деструкторе локальную переменную через delete - чревато.

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

Это сообщение отредактировал(а) boostcoder - 14.8.2010, 15:25
PM WWW   Вверх
SABROG
Дата 14.8.2010, 15:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(boostcoder @  14.8.2010,  15:09 Найти цитируемый пост)
они легко могут быть автоматическими переменными

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


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
boostcoder
Дата 14.8.2010, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(SABROG @  14.8.2010,  15:31 Найти цитируемый пост)
Ситуации разные бывают

да. но вашим кодом, вы обязываете пользователя использовать new.
PM WWW   Вверх
SABROG
Дата 14.8.2010, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(boostcoder @  14.8.2010,  15:54 Найти цитируемый пост)
да. но вашим кодом, вы обязываете пользователя использовать new.


Дык то ж не я, это умный указатель обязывает. Да и сам по себе синглтон тоже много чего обязывает, никто ж не ругается.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
SABROG
Дата 16.8.2010, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



В общем как обычно, с этими интерфейсами больше проблем.

Код

class IDownloadManager
{
public:
    typedef QSharedPointer<IDownloadManager> Ptr;
    virtual ~IDownloadManager() {}
};
...
class DownloadManager : public QObject, public IDownloadManager
{
    Q_OBJECT
public:
    explicit DownloadManager(QObject *parent = 0);

signals:

public slots:

};


Далее в коде нужно передавать указатель типа QObject во внутренние классы Qt. И тут возникает проблема downcast'инга от класса интерфейса да DownloadManager'a. В общем каждая собачка - зверушка, но не каждая зверушка - собачка. Наследовать интерфейсы от QObject'a тоже как-то не хочется, как-то это не легковесно.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
mes
Дата 17.8.2010, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(SABROG @  16.8.2010,  16:42 Найти цитируемый пост)
 передавать указатель типа QObject во внутренние классы Qt

Цитата(SABROG @  16.8.2010,  16:42 Найти цитируемый пост)
от класса интерфейса 

все зависит от того, что должен выражать интерфейс.. 




--------------------
PM MAIL WWW   Вверх
SABROG
Дата 17.8.2010, 10:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(mes @  17.8.2010,  09:58 Найти цитируемый пост)
все зависит от того, что должен выражать интерфейс.. 

Да я и сам не знаю smile Хотелось реализовать вариант dependency injection в противовес одиночке. Пока получаю один геморрой. Уже неделю не могу начать писать хоть что-то, всё архитектуру придумываю и каждый раз её приходиться заново переписывать.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Леопольд
Дата 17.8.2010, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



SABROG, не пойму, чем это лучше обычного синглтона... К тому же, если скорость критична (не просто так ведь заботишься о расходах на синхронизацию кэша ядер?), то виртуальные вызовы не лучший вариант.

Если не обойтись без downcasting'а, но dynamic_cast недопустим (в релизе), то можно использовать checked_cast... Я его выдернул из книги Александреску и Саттера "Стандарты программирования на С++"
Хотя, IMHO лучше всё же обойтись...

Это сообщение отредактировал(а) Леопольд - 17.8.2010, 10:45


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
SABROG
Дата 17.8.2010, 15:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(Леопольд @  17.8.2010,  10:35 Найти цитируемый пост)
то виртуальные вызовы не лучший вариант.

А разве есть какой-нибудь оверхед, если метод интерфейса чисто виртуальный?

Код

virtual void foo() = 0;



--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
mes
Дата 17.8.2010, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(SABROG @  17.8.2010,  14:03 Найти цитируемый пост)
А разве есть какой-нибудь оверхед, если метод интерфейса чисто виртуальный?

от чистоты ничего не зависит. 
виртуальный вызов более дорогостоящ, чем _прямой_.

и еще не понял, какая связь между синглетоном и  Dependency Injection в рамках этой темы ? 
одно не альтернатива другому, а дополнение.

Это сообщение отредактировал(а) mes - 17.8.2010, 18:20


--------------------
PM MAIL WWW   Вверх
SABROG
Дата 17.8.2010, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 4
Всего: 91



Цитата(mes @  17.8.2010,  18:13 Найти цитируемый пост)
и еще не понял, какая связь между синглетоном и  Dependency Injection в рамках этой темы ? 
одно не альтернатива другому, а дополнение.

Разве? Разница такая вроде бы:

// Dependency Injection
Код

MyClass::MyClass(Settings* settings)
{
    OtherClass* oc = new OtherClass(settings);
    int size = settings->value("size").toInt();
}

OtherClass::OtherClass(Settings* settings)
{
    std::string str = settings->value("user").toString();
}


// Singleton

Код

MyClass::MyClass()
{
    int size = Settings::instance()->value("size").toInt();
}

OtherClass::OtherClass()
{
    std::string str = Settings::instance()->value("user").toString();
}



--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1989 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.