Re[18]: Singleton действительно антипаттерн в enterprize при
От: adontz Грузия http://adontz.wordpress.com/
Дата: 12.08.07 19:13
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Псевдокод можно? А то словами у тебя както не очень получилось объяснить.


Можно.

БЫЛО
// типы
template <typename T>
class singleton
{
    public:
        static T & get_instance()
        {
            static T instance;
            
            return instance;
        }
};

class logger
{
    friend singleton<logger>;

    private:
        logger();
    public:
        void log(const char * message) const;
}
// использование
singleton<logger>.get_instance().log("some text");

СТАЛО
// типы
template <typename T>
class singleton
{
    public:
        static T & get_instance()
        {
            static T instance;
            
            return instance;
        }
};

class logging_part
{
    public:
        virtual void log(char * message, bool * is_canceled, bool * is_handled) = 0;
}

class text_logging_part : public logging_part
{
    public:
        virtual void log(char * message, bool * is_canceled, bool * is_handled);
}

class db_logging_part : public logging_part
{
    public:
        virtual void log(char * message, bool * is_canceled, bool * is_handled);
}

class logger
{
    public:
        void log(const char * message) const;    
        void add_part(logging_part * log, /* какие-то параметры указывающие приоритет вызова и т.п. */);
        void remove_part(logging_part * log);
}
// использование
text_logging_part tl;
db_logging_part dl;

singleton<logger>.get_instance().add_part(tl);

singleton<logger>.get_instance().add_part(dl);

// Вот тут ничего не поменялось. Если нужна ещё и бинарная совместимость, то делаем интерфейсы.
singleton<logger>.get_instance().log("some text");


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

WH>Ни разу со временем жизни проблем не возникало.

Проблема очевидная. Пишешь managed обёртку в виде какого-нибудь

class ManagedWrapper
{
    public event RakeEventHandler Rake
    {
        add
        {
            NativeMethods.AddCallbackTarget(value, GetContextForObject(value).ToIntPtr());
        }

        remove
        {
            NativeMethods.RemoveCallbackTarget(value, GetContextForObject(value).ToIntPtr());
        }
    }
}

и потом в коде
ManagedWrapper mw;

mw.Rake += MyHandler;

И получаешь грабли, потому что делегат указывавший на метод MyHandler был собран сборщиком мусора как неимеющий managed ссылок. Прямо скажем — неприятно. Приходится переписывать в виде
class ManagedWrapper
{
    public event RakeEventHandler Rake
    {
        add
        {
            SomeGlobalDelegateTable.Add(value);
            NativeMethods.AddCallbackTarget(value, GetContextForObject(value).ToIntPtr());
        }

        remove
        {
            NativeMethods.RemoveCallbackTarget(value, GetContextForObject(value).ToIntPtr());
            SomeGlobalDelegateTable.Remove(value);
        }
    }
}

потому что заставлять клиента явно создавать делегат и хранить на него ссылку не катит.
Таких сюрпризов у меня в своё время было не мало.

WH>Я вот не помню ни одного случая когда отложенная инициализация имела смысл.


Случай простой — инициализация тяжёлая операция и не всегда нужная. Мне, например, не нравятся приложения стартующие 2-3 минуты потому что программист не стал заморачиваться и решил инициализировать всё сразу.
A journey of a thousand miles must begin with a single step © Lau Tsu
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.