Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.76/21: Рейтинг темы: голосов - 21, средняя оценка - 4.76
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826

Масштабирование системы при использовании паттерна Singleton

04.01.2017, 10:51. Показов 4777. Ответов 85
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день, как доказать или опровергнуть, что архитектура теряет гибкость и расширяемость при активном использовании паттерна Singleton.
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.01.2017, 10:51
Ответы с готовыми решениями:

Насчёт шаблонного паттерна SingleTon
Есть код паттерна template<class T> class Singleton { private: static T* ptr; protected: Singleton();

Необходима альтернатива при использовании Proxy паттерна
Здравствуйте, возникла проблема, которую я так и не придумал, как рационально решить. В общем, задача состояла в том, чтобы отследить...

Реализация паттерна Singleton
Добрый день. Необходимо реализовать класс Storage, объект которого будет единственным в программе. Для достижения данной цели было выбрано...

85
4949 / 2289 / 287
Регистрация: 01.03.2013
Сообщений: 5,991
Записей в блоге: 32
08.01.2017, 19:28
Студворк — интернет-сервис помощи студентам
gru74ik, да любыми - их море и выше уже многие написаны (скорее всего, пока детально не читал ) В С++/Жаве/С# - статическими полями/методами класса без создания экземпляров, в С++ из-за сишного наследия добавляется еще вариант свободных функций и глобальных переменных - хоть в отдельном нэймспейсе в виде сишного модуля (тут что-то писали выше про это). Но я подозреваю, что есть и еще варианты.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
08.01.2017, 19:29
Цитата Сообщение от daslex Посмотреть сообщение
Написать верхушку, которую сделать синглтоном, от неё унаследовать первоначальную SQL и новую требуемую.
Это несерьёзно.
Что вы подразумеваете под верхушкой и что туда нужно положить?
Посмотрите API для работы с MySQL и SQLite, они используют разные функции для работы с БД(но зачастую одинаковые по смыслу). В целом наследовать в плане БД-зависимых вещей почти нечего. Тут нужна конкретная реализация, а именно адаптер для каждой БД, который позволит сохранить единый интерфейс а под капотом реализации будут отличатся, для каждой БД - своя

Цитата Сообщение от daslex Посмотреть сообщение
Товарищи, скажите мне вот что, есть ли в контексте паттернов термин масштабируемости?
Паттерн это просто подход к решению задачи, которую решали уже 100 раз при проектировании и эмперическим путем было выявлено что в определенных случаях определенное решение очень эффективно. Сам по себе паттерн ничего не делает, все упирается в то насколько разработчик хорошо его применяет там где это нужно
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
08.01.2017, 19:46
приведите пример.
Любой пример сведётся, он должен свестись к неудачному выбору реализации, не так ли?
Это к Hoggy.

Добавлено через 5 минут
Цитата Сообщение от sys_beginner Посмотреть сообщение
Что вы подразумеваете под верхушкой и что туда нужно положить?
Я имею в виду, что синглтон - это одна сущность.
Если однотипных сущностей две - это уже не синглтон, но сделать синглтон, который будет влиять на два экссинглтона, не представляется сложностью.

Добавлено через 2 минуты
Цитата Сообщение от sys_beginner Посмотреть сообщение
Посмотрите API для работы с MySQL и SQLite, они используют разные функции для работы с БД(но зачастую одинаковые по смыслу).
Полиморфизм никто не отменял.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
08.01.2017, 19:53
Цитата Сообщение от daslex Посмотреть сообщение
но сделать синглтон, который будет влиять на два экссинглтона не представляется сложностью.
Увы, не могу комментировать. Не понял, что вы имели ввиду

Добавлено через 46 секунд
Цитата Сообщение от daslex Посмотреть сообщение
Полиморфизм никто не отменял.
Я знаю О нем и речь
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
08.01.2017, 21:15

Не по теме:

Кашу варим на потолке козы.



Добавлено через 53 минуты

Не по теме:

Я понял, что Вы имели в виду.



Добавлено через 5 минут

Не по теме:

И не понял каким боком тут полиморфизм. Его не было, нет и не будет: ничего не испорчено.
Это тот случай, когда синглтон мешает полиморфизму, но не тот случай, когда

В зависимости от задачи и дальнейших потребностей синглтон может сильно навредить.
Это сам себе злобный буратино вредитель, а не синглтон. С потенциальным таким исходом буратине синглтон изначально не нужен.

0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
08.01.2017, 21:30
Цитата Сообщение от daslex Посмотреть сообщение
И не понял каким боком тут полиморфизм
Значит не поняли Работа с разными реализациями как с единым типом это есть частный случай полиморфизма

Цитата Сообщение от daslex Посмотреть сообщение
Это сам себе злобный буратино вредитель, а не синглтон.
Я в том смысле, что заранее неизвестно какое направление примет программа при развитии, это ограничено лишь фантазией клиента. Можно конечно расширить программу при всяком раскладе, но вопрос - какой ценой? Используя синглтон разработчик накладывает определенные ограничения на свою реализацию, что при определенном развитии событий может привести к неприятным последствиям, которых просто могло и не быть, будь разработчик более дальновидным в плане архитектурных решений.
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
08.01.2017, 21:48
А вот я вырезку делаю из книжки GOF.
Обращаем внимание на дисплеи. И быстро проводим аналогию к БД. Неужто непохожие случаи? Там что-то было испорчено?

Известные применения.
Миниатюры
Масштабирование системы при использовании паттерна Singleton  
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
08.01.2017, 22:02
Цитата Сообщение от sys_beginner Посмотреть сообщение
Значит не поняли
Это Вы меня не поняли.
Там, где изначально одна форма, где у этой формы по природе своей других форм никогда не существовало, полиморфизма нет и быть не может.

Если появляется другая форма такого же типа, то есть возможность полиморфизма, и существует соблазн к полиморфизму, но он не обязательно доступен. Если при всей недоступности полиморфизма, но при наличии большого числа других возможностей, бракуется какой-то принцип, то это только по причине полиморфизма головного мозга, а не по причине убыточности принципа.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
08.01.2017, 22:18
Цитата Сообщение от daslex Посмотреть сообщение
Там, где изначально одна форма, где у этой формы по природе своей других форм никогда не существовало, полиморфизма нет и быть не может.
Ну да. Но что если заранее подготовиться к возможному расширению?
Усилия конкретно в данном случае будут настолько минимальные что вести речь об этом даже и не стоит.
И не придется браковать один из доступных и удобных принципов

Ладно...
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,886
08.01.2017, 23:12
Ну. Я кое в чём солидарен.
Просто, если бы идеология паттерна "синглтон" доносилась немного в другом ключе, то было бы, наверное, как-то лучше:
Если создавать второй экземпляр класса неестественно и опасно, используйте правильный синглтон.

Как-нибудь так. Слово "правильный" мной употреблено только от того, что нет оптимальной реализации шаблона синглтон, но есть семейство реализаций, с которого можно выбрать.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
09.01.2017, 00:06
Цитата Сообщение от daslex Посмотреть сообщение
Если создавать второй экземпляр класса неестественно и опасно, используйте правильный синглтон.
Святые слова. Тут каждый (я в т.ч.) нечто подобное изрек. Но не видно решающих доводов в пользу того, что это нужно делать через экземпляр класса. Статические методы вполне поддерживают статический полиморфизм. Полиморфизм наследования? Без экземпляров таки не возможен, но хотелось бы пример. Я с трудом представляю контейнер указателей на базовый класс синглтона и алгоритм который его использует. То есть, сначала мы запрещаем использовать класс как источник перечислимых сущностей - объектов (форум не знает род. падежа "сущность") чтобы всё делалось строго под контролем одного-единственного, а потом создаём контейнер полиморфных указателей и реализуем алгоритм которому начхать какой конкретно синглтон выполнит то или иное действие... Можно в каждом синглтоне создать указатель на базовый как поле и получать потом списки. Дрожь пронимает от самой мысли о том какое зло можно сотворить. Плодотворно.
Это шутки. Но если серьёзно, то для использования полиморфного наследования, хочется пример.
Я пока увидел только перегрузку операторов. Дело было так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
template<class T>
class Sp;//смарт - буквально - пойнтер )))
 
template<class T>//сиглтон (Майерса)//менеджер памяти
class GC
{
friend class Sp<T>;
map< T*, int> mapp;//pointers
map< T*, pair<int /*cnt*/, int /*siz*/>> mapa;//array pointers
GC(){}
 GC( const GC&);  
    GC& operator=( GC& );
public:
void Add(T *rhs);//добавляем в mapp (одиночные) 
void AddNew(T *rhs,int sz);//добавляем в mappa - (дин массивы)
bool remove(T *rhs);
public:
T *GCNEW(const T &rhs)
{
T *ptr = new T(rhs);
AddNew(ptr);
return ptr;
}
 
T *operator()(const T &rhs)
{
T *ptr = new T(rhs);
AddNew(ptr);
return ptr;
}
T *operator[](int rhs)
{
T *ptr = new T[rhs];
AddNew(ptr, rhs);
return ptr;
}
//остальное неважно
};
template<class T>
class Sp
{
    friend class GC<T>;
 
T *ptr;
 
 
public:
    static GC<T> &NEW;
static const T *GCNEW(const T &rhs)
{
T *ptr_new=gc->GCNEW(rhs);
return ptr_new;
}
~Sp()
{
NEW.remove(ptr);
}
 
Sp()
{
ptr=NULL;
}
 
Sp(const T &rhs)
{
if(this!=rhs)
{
ptr = &rhs;
NEW.Add(ptr);
}
}
 
 
Sp(const T *rhs)
{
if(ptr!=rhs)
{
ptr = const_cast<T*>(rhs);
NEW.Add(ptr);
}
}
 
Sp(const Sp &rhs)
{
if(this!=&rhs)
{
ptr = rhs.ptr;
NEW.Add(ptr);
}
}
 
Sp &operator=(const Sp &rhs)
{
if(this==rhs)return *this;
NEW.remove(ptr);
ptr=rhs.ptr;
NEW.Add(ptr);
return *this;
}
 
Sp &operator=(T * rhs)
{
if(this.ptr==rhs)return *this;
NEW.remove(ptr);
ptr=const_cast<T*>(rhs);
NEW.Add(ptr);
return *this;
}
 
const T *operator->()const{return ptr;}
const T &operator*()const{return *ptr;}
//эти перегрузки должны сопровождаться изменениями в базе mapp
//поскольку теряется прежнее значение указателя ptr
 
T &operator[](int ind){return *(ptr+ind);}
size_t get_size()
{
size_t  ret=0;
ret=NEW.get_size(ptr);
return ret;
}
};
 
template<typename T>
GC<T> &Sp<T>::NEW= GC<T>::getInstance();
Вся история из-за операторов () и [] у класса управляющего памятью для объектов соответствующего типа - синглтона
То есть в коде можно использовать имя экземпляра NEW со скобками или с квадратными скобками, выделяя память под одиночные объекты или под массивыцепочки в динамической памяти. То есть так как это пишется с оператором new.
C++
1
2
3
4
ValType obj;
Sp<ValType> pobj=Sp<ValType>::NEW(&obj);
//или
Sp<ValType> sp_dynamic_array=Sp<ValType>::NEW[10];
всё это получилось достаточно несложно. Хотя по другому я придумать не смог.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
11.01.2017, 13:04
Цитата Сообщение от sys_beginner Посмотреть сообщение
В случае DI, можно будет просто передать адаптер который больше подходит для запроса пользователя.
и после этого пользователям придется знать о его существовании.
проблема DI - на многострадальную голову пользователей
начинают вываливаться куча всяких архитектурных подробностей:
интерфейсы, реализации, etc.

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

Цитата Сообщение от sys_beginner Посмотреть сообщение
А в случае синглтона придется серьезно рефакторить код
нафига?

мы ж просто добавляем поддержку ещё одной базы,
но интерфейс сингелтона же не меняется.

где то в коде, где нибудь в майне вместо:

C++
1
2
// устаревшее соединением с мускулом
db::connect(params);
сделаем возможность указать тип базы:

C++
1
2
db::connect<MYSQL>(params);
db::connect<POSTGRESQL>(params);
остальной же код запросов останется без изменений.
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
11.01.2017, 14:23
Цитата Сообщение от hoggy Посмотреть сообщение
интерфейсы, реализации, etc.
За то более выразительно выглядит и все расставлено по полочкам

Насколько я понял, вы предлагаете вызывать getInstance() от T, вместо указания конкретного типа?
Это конечно решает проблему расширяемости(но не в общем, а именно в С++, потому что если говорить об ООП в целом, в многих или даже всех остальных языках нет шаблонов).

Но даже в таком случае на каждую модель(если говорить в контексте MVC, тобишь каждый дата-провайдер) который использует этот T будет сгенерирован ровно столько раз сколько у нас будет типов БД в поддержке, разве нет?

А что если таких дата провайдеров пол сотни или более? В реальных программах такое часто бывает. В итоге получим приличный оверхед в исходном коде.

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

Добавлено через 12 минут
Цитата Сообщение от sys_beginner Посмотреть сообщение
в многих или даже всех остальных языках нет шаблонов
В Java помоему есть generic, что то вроде шаблонов.
Но тем не менее данная стратегия языкозависимая и все таки думаю приводит к оверхеду по исходному коду
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
11.01.2017, 14:41
Цитата Сообщение от sys_beginner Посмотреть сообщение
За то более выразительно выглядит и все расставлено по полочкам
выразительно оно когда не светит всякие детали собственной реализации.
чем меньше всего нужно знать, помнить,
и держать в голове, тем лучше.

Цитата Сообщение от sys_beginner Посмотреть сообщение
Насколько я понял, вы предлагаете вызывать getInstance() от T, вместо указания конкретного типа?
не понял вопроса.

что именно не понятно в приведем кусочке?
C++
1
2
db::connect<MYSQL>(params);
db::connect<POSTGRESQL>(params);
юзер указывает с кем хочет соединиться.
MYSQL и POSTGRESQL - это могут быть обычные enum

при этом его совершенно не парит,
как именно сингелтон будет это обеспечивать.

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

Цитата Сообщение от sys_beginner Посмотреть сообщение
Это конечно решает проблему расширяемости(но не в общем, а именно в С++, потому что если говорить об ООП в целом, в многих или даже всех остальных языках нет шаблонов).
мы не тратим время на пустую болтовню об "ооп в целом".
мы находимся в ветке с++, именно с++ специфику.
и мы используем всю мощь и выразительность этого языка.

Цитата Сообщение от sys_beginner Посмотреть сообщение
Но даже в таком случае на каждую модель(если говорить в контексте MVC, тобишь каждый дата-провайдер) который использует этот T будет сгенерирован ровно столько раз сколько у нас будет типов БД в поддержке, разве нет?
А что если таких дата провайдеров пол сотни или более? В реальных программах такое часто бывает. В итоге получим приличный оверхед в исходном коде.
не осилил этот поток сознания.

Добавлено через 2 минуты
Цитата Сообщение от sys_beginner Посмотреть сообщение
В Java помоему есть generic, что то вроде шаблонов.
в ветке посвященной с++ это не очень интересно.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
11.01.2017, 16:47
Цитата Сообщение от hoggy Посмотреть сообщение
что именно не понятно в приведем кусочке?
А можете показать момент вызова функции с использованием этого скрытого адаптера? Вот есть у вас для простоты одна функция, которая должна отбработать то через postgre то через mysql. Как будете её вызывать?

Цитата Сообщение от hoggy Посмотреть сообщение
всю мощь и выразительность этого языка
Заметил, вы очень любите так выражаться

Добавлено через 6 минут
Цитата Сообщение от sys_beginner Посмотреть сообщение
Вот есть у вас для простоты одна функция, которая должна отбработать то через postgre то через mysql. Как будете её вызывать?
Например
C++
1
2
3
4
5
6
7
8
class ProductDataProvider
{
    public:
    Product* getProductById(int id)
    {
        //нужно взять продукт либо из  postge либо из mysql в зависимости от запроса юзера программы
    }
};
0
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
11.01.2017, 17:01
Цитата Сообщение от sys_beginner Посмотреть сообщение
//нужно взять продукт либо из *postge либо из mysql в зависимости от запроса юзера программы
Скорее всего будет по-другому.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/////////////////////////////////////////////////////////////////////////////////////////
class IBDType
{
public:
    virtual ~IBDType() = default;
    virtual Product* getProductById() = 0;
};
/////////////////////////////////////////////////////////////////////////////////////////
class PostgreSQL : public IBDType
{
public:
    virtual Product* getProductById(int) override
    {
        //some code
    }
};
/////////////////////////////////////////////////////////////////////////////////////////
class MySQL : public IBDType
{
public:
    virtual Product* getProductById(int) override
    {
        //some code
    }
};
/////////////////////////////////////////////////////////////////////////////////////////
//in singleton
class bd
{
public:
    //...
    static Product* getProductById(int id)
    {
        switch(BDType)
        {
            case MYSQL:
                return dynamic_cast<MySQL*>(bd)->getProductById(id);
            case POSTGRESQL:
                return dynamic_cast<PostgreSQL*>(bd)->getProductById(id);
            //...
        }
    }
    //...
};
/////////////////////////////////////////////////////////////////////////////////////////
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
11.01.2017, 17:06
Цитата Сообщение от GbaLog- Посмотреть сообщение
Скорее всего будет по-другому
То о чем я говорил позволяет не делать всего этого )) Об и речь
0
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
11.01.2017, 17:08
Цитата Сообщение от sys_beginner Посмотреть сообщение
о чем я говорил
Тему долго читать, можете привести минимальный кусок кода с теми же MySQL и PostgreSQL?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
11.01.2017, 17:46
Цитата Сообщение от GbaLog- Посмотреть сообщение
Тему долго читать, можете привести минимальный кусок кода с теми же MySQL и PostgreSQL?
Ага. Обратите внимание на main

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
 
#define SOURCE_MYSQL 0
#define SOURCE_POSTGRE 1
 
class DbAdapter
{
    public:
    virtual bool query(std::string sql) = 0;
};
 
class MySQLAdapter : public DbAdapter
{
    public:
    bool query(std::string sql) override
    {
        //call mysql_specific_query_function(sql);
        return true;
    }
};
 
class PostgreSQLAdapter : public DbAdapter
{
    public:
    bool query(std::string sql) override
    {
        //call mysql_postgre_specific_query_function(sql);
        return true;
    }
};
 
class Product
{
    bool productData;
    public:
    Product(bool data)
    {
        productData = data;
    }
    
};
 
class ProductDataProvider
{
    DbAdapter *adapter;
    public:
    ProductDataProvider(DbAdapter *a)
    {
        setAdapter(a);
    }
    ProductDataProvider* setAdapter(DbAdapter *a)
    {
        adapter = a;
        return this;
    }
    
    Product* getProductById(int id)
    {
        bool result = adapter->query("query using id...");
        return new Product(result);//based on query result
    }
};
 
int main()
{
    ProductDataProvider provider = ProductDataProvider(new MySQLAdapter);
    Product *prodFromMysql = provider.getProductById(1);
    
    //предположим что значение source мы получили от пользователя
    int source = SOURCE_POSTGRE;
    if (source == SOURCE_POSTGRE) {
        Product *prodFromPostgre = provider.setAdapter(new PostgreSQLAdapter)->getProductById(1);
    }
}
bool было использовано в качестве аргумента для продукта для простоты, реальности там была бы цена название и т.д

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

Добавлено через 3 минуты
И нет необходимости в каждой функции дата провайдера выяснять какой адаптер использовать как это сделано у вас
А если таких провайдеров и функций сотни?

Добавлено через 10 минут
Можно даже для определения source на if Не проверять а создать map, где ключом будет source, а значением - адаптер
Просто достаем в зависимости от запроса из map указатель на нужный адаптер подставляя запрос пользователя в map как ключ и пользуясь значением этого ключа(адаптером) дергаем data source
0
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
11.01.2017, 17:49
Цитата Сообщение от sys_beginner Посмотреть сообщение
И нет необходимости в каждой функции дата провайдера выяснять какой адаптер использовать
Правда? А это что такое?
Цитата Сообщение от sys_beginner Посмотреть сообщение
if (source == SOURCE_POSTGRE)
Как и говорил hoggy, слишком много потрохов вы выдаёте наружу. Пользователь не хочет знать, как там устроено всё, пользователю нужно получить продукт.
Цитата Сообщение от sys_beginner Посмотреть сообщение
как просто происходит переключение между источниками данных
Ну ладно, переделываем так и всё. И пользователь продукт получает, и мы реализацию закрываем.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/////////////////////////////////////////////////////////////////////////////////////////
class IBDType
{
public:
    virtual ~IBDType() = default();
    virtual Product* getProductById() = 0;
};
/////////////////////////////////////////////////////////////////////////////////////////
class PostgreSQL : public IBDType
{
public:
    virtual Product* getProductById(int) override
    {
        //some code
    }
};
/////////////////////////////////////////////////////////////////////////////////////////
class MySQL : public IBDType
{
public:
    virtual Product* getProductById(int) override
    {
        //some code
    }
};
/////////////////////////////////////////////////////////////////////////////////////////
typedef PostgreSQL POSTGRESQL;
typedef MySQL MYSQL;
/////////////////////////////////////////////////////////////////////////////////////////
//in singleton
class bd
{
public:
    //...
    template<typename BDType, typename... Args>
    static void connect(Args&&... args)
    {
        if (BDBase == nullptr)
            BDBase = new BDType(std::forward<Args>(args));
        else
        {
            delete BDBase;
            BDBase = new BDType(std::forward<Args>(args));
        }
    }
    
    static Product* getProductById(int id)
    {
        return BDBase->getProductById(id);
    }
    
    IBDType* BDBase;
    //...
};
/////////////////////////////////////////////////////////////////////////////////////////
int main()
{
    bd::connect<POSTGRESQL>();
    Product* p1 = bd::getProductById(1);
    bd::connect<MYSQL>();
    Product* p2 = bd::getProductById(1);
}
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
11.01.2017, 17:49

Может ли потребоваться применение механизма событий при использовании паттерна MVVM?
Паттерн MVVM провозглашён как базовый паттерн для приложений WPF. В паттерне MVVM используется механизм команд. То есть, если...

Настройка системы при использовании SSD
Здравствуйте. Хотелось бы знать, нужно ли настраивать систему при использовании SSD.

Постоянно прохожу проверку CAPTCHA при использовании поисковой системы
Доброго времени суток. Проблема следующая: при поиске в гугле или яндексе эти поисковые системы постоянно запрашивают пройти проверку...

Collections: singleton/singletonList/singletonMap. Что значит слово singleton?
Заметил, что в классе Collections (утилитный класс) имеются методы для оборачивания элемента в set/list/map Все эти методы содержат в...

Установка "лимита" на значение решения системы ОДУ при использовании решателя ode45
Добрый день. Есть такая задачка: при решении системы дифференциальных уравнений, пусть одно из решений имеет величину, условно говоря, с 1...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
80
Ответ Создать тему
Новые блоги и статьи
Море в объективе
kumehtar 06.07.2026
Хотел написать много проникновенных слов, но передумал. Оно само - говорит. Кто слышит тот слышит.
Оказывается, Unreal Engine позволяет качество на порядки выше, чем было в Lineedge
Etyuhibosecyu 05.07.2026
Жаль, конечно, что я не узнал об этом, пока Lineedge существовала, а то бы Noname2331 написал, что волки превращаются в пиксельную кашу, а я бы его попросил скачать какую-нибудь бриллиантовую или Pro. . .
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась. Первый вариант. . .
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2. Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru