Здравствуйте, zelenprog, Вы писали:
Z>Я читал, что это анти-паттерн. Но как сделать по другому?
Сделайте Adapter параметром метода Init.
Z>Второй вопрос. Кто (какой объект) должен отвечать за проверку типа базы и создание конкретного Адаптера?
Очевидно, AdapterFactory.
Приведённый вами случай отличается от заявленного в начале топика.
Тут у вас инициализация ридера требует фиксированного набора параметров, поэтому ничто не мешает внести их в метод Init (раз уж вы твёрдо решили обойтись без параметров в конструкторе).
По крайней мере у вас чётко будет 2 состояния у объекта: до инициализации и после инициализации; и гарантированно не будет "недоинициализированного" объекта (как могло бы быть, если бы установка отдельных свойств делалась отдельными вызовами со сложным ветвлением).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: "Гибкий" конструктор для инициализации объекта класса (аналог Dispose)
Здравствуйте, Sinclair, Вы писали:
S>Приведённый вами случай отличается от заявленного в начале топика.
Отличается только как частное к общему: последний пример — это частный случай той проблемы, которая была описана в первом топике.
S>Тут у вас инициализация ридера требует фиксированного набора параметров, поэтому ничто не мешает внести их в метод Init (раз уж вы твёрдо решили обойтись без параметров в конструкторе). S>По крайней мере у вас чётко будет 2 состояния у объекта: до инициализации и после инициализации; и гарантированно не будет "недоинициализированного" объекта (как могло бы быть, если бы установка отдельных свойств делалась отдельными вызовами со сложным ветвлением).
Во-о-от. То есть от метода Init в данной ситуации нельзя избавиться. Причем этот метод придется использовать в большинстве классов.
Получается, использование метода Init надо "подчинить" каким-то правилам, чтобы везде его использование в коде было однозначным.
То есть мы приходим к необходимости "оформления" нового "шаблона" создания и инициализации объектов.
Об этом я и спрашивал в первом топике: "есть ли какие-либо устоявшиеся шаблоны\методики\практики более "гибкого" выделения ресурсов в дополнение к конструктору класса"?
Ведь для уничтожения объектов разработали общепринятый IDisposable.
Значит, еще нужен и IInitialaizable.
Re[4]: "Гибкий" конструктор для инициализации объекта класса (аналог Dispose)
Здравствуйте, zelenprog, Вы писали:
Z>Ведь для уничтожения объектов разработали общепринятый IDisposable. Z>Значит, еще нужен и IInitialaizable.
Положа руку на сердце, это выглядит как решение искусственно созданной проблемы.
Вот в дотнете конструктор уже является "методом Init", просто языки вроде C# более-менее следят за тем, чтобы не дать программисту воспользоваться объектом в недоинициализированом состоянии.
С точки зрения CLR, к моменту вызова конструктора объект уже полностью сконструирован — у него корректная VMT, и в полях нет никакого булшита (который мог бы помешать работе GC — например, случайные ссылки).
То есть авторы шарпа постарались максимально скрыть от пользователя этот зазор между "конструктором" и "Init". А вы зачем-то выпячиваете его наружу.
Фактически, тщательно переносите в рантайм проверку, которую прекрасно мог взять на себя компилятор.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: "Гибкий" конструктор для инициализации объекта класса (аналог Dispose)
S>Положа руку на сердце, это выглядит как решение искусственно созданной проблемы.
Это не искусственная проблема.
Это особенность "моей" платформы.
S>Вот в дотнете конструктор уже является "методом Init", просто языки вроде C# более-менее следят за тем, чтобы не дать программисту воспользоваться объектом в недоинициализированом состоянии. S>С точки зрения CLR, к моменту вызова конструктора объект уже полностью сконструирован — у него корректная VMT, и в полях нет никакого булшита (который мог бы помешать работе GC — например, случайные ссылки). S>То есть авторы шарпа постарались максимально скрыть от пользователя этот зазор между "конструктором" и "Init". А вы зачем-то выпячиваете его наружу. S>Фактически, тщательно переносите в рантайм проверку, которую прекрасно мог взять на себя компилятор.
>> авторы шарпа постарались максимально скрыть от пользователя этот зазор между "конструктором" и "Init". А вы зачем-то выпячиваете его наружу. >> Фактически, тщательно переносите в рантайм проверку, которую прекрасно мог взять на себя компилятор.
Потому что моя среда разработки не умеет делать того, что вы описали.
Она позволяет делать классы, но у них конструкторы без параметров.
Нету статических классов, свойств и методов. Нету виртуальных функций.
Нету типизации и контроля типов, любая переменная или параметр может быть любого типа.
Приходится "вручную" добавлять эти недостающие возможности ООП.
Re[2]: "Гибкий" конструктор для инициализации объекта класса
Можно сделать вспомогательные функции приложения таким образом, чтобы ...
// global function
I_DBAdapter MakeDBAdapter(string pFileName) // 1
{
I_DBAdapter lDBAdapter = null;
T_DatabaseInfo lDatabaseInfo = new T_DatabaseInfo(pFileName);
if lDatabaseInfo.DBType = Database.DBType1 then
lDBAdapter = new T_DBAdapter1(pFileName);
elseif lDatabaseInfo.DBType = Database.DBType2
lDBAdapter = new T_DBAdapter2(pFileName);
else
// исключение "неизвестный тип БД
endif
return lDBAdapter;
}
// global function
T_DBGoodsReader MakeDBGoodsReader(string pFileName) // 2
{
T_DBGoodsReader lDBGoodsReader = new T_DBGoodsReader;
I_DBAdapter lDBAdapter = MakeDBAdapter(pFileName); // 1
lDBGoodsReader.SetAdapter(lAdapter);
lDBGoodsReader.Init();
return lDBGoodsReader;
}
... Чтобы их было легче использовать
Class MainForm
{
string mFileName;
void OnButton_ReadDatabase()
{
T_DBGoodsReader lDBGoodsReader = MakeDBGoodsReader(mFileName); // 2
lDBGoodsReader.Read();
// показать на форме список товаров
}
}
--
Я просто переорганизовал ваш код
Z>
Z>Class MainForm
Z>{
Z> string mFileName;
Z> void OnButton_ReadDatabase()
Z> {
Z> T_DatabaseInfo lDatabaseInfo = new T_DatabaseInfo(mFileName);
Z> T_DBGoodsReader lDBGoodsReader = new T_DBGoodsReader;
Z> I_DBAdapter lDBAdapter = null;
Z> if lDatabaseInfo.DBType = Database.DBType1 then
Z> lDBAdapter = new T_DBAdapter1(mFileName);
Z> elseif lDatabaseInfo.DBType = Database.DBType2
Z> lDBAdapter = new T_DBAdapter2(mFileName);
Z> else
Z> // исключение "неизвестный тип БД
Z> endif
Z> lDBGoodsReader.SetAdapter(lAdapter);
Z> lDBGoodsReader.Init();
Z> lDBGoodsReader.Read();
Z> // показать на форме список товаров
Z> }
Z>}
Z>
Скажем чтобы он мог сгенерировать для класса SomeClass
... глобальную функцию SomeClass_make()
... в которой параметры те-же, что и в методе Init() того же класса
а тело функции make примерно такое:
SomeClass_make(int param1, string param2)
{
SomeClass ret = new SomeClass;
ret.Init(param1, param2);
return ret;
}
Чтобы просто форвардить параметры в init
т.е Компилятор знает параметры в init и может их обработать, так?
Но если в классе нет init, то и SomeClass_make() видимо не нужен.
Здравствуйте, zelenprog, Вы писали:
S>>Положа руку на сердце, это выглядит как решение искусственно созданной проблемы.
Z>Это не искусственная проблема. Z>Это особенность "моей" платформы.
1С?
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[7]: "Гибкий" конструктор для инициализации объекта класса (аналог Dispose)
Здравствуйте, Разраб, Вы писали:
Z>>Это не искусственная проблема. Z>>Это особенность "моей" платформы. Р>1С?
Да. Не хотелось этого афишировать.
Боюсь, что упоминание про 1С уведет обсуждение в сторону.
А мне хотелось бы и на 1С написать программу с "правильным" подходом и "правильной" архитектурой. Нужно только придумать как грамотно преодолеть некоторые ограничения платформы.
S>У вас есть возможность доработать ваш компилятор?
Нет такой возможности.
S>Скажем чтобы он мог сгенерировать для класса SomeClass S>... глобальную функцию SomeClass_make() S>... в которой параметры те-же, что и в методе Init() того же класса S>а тело функции make примерно такое: S>
S>SomeClass_make(int param1, string param2)
S>{
S> SomeClass ret = new SomeClass;
S> ret.Init(param1, param2);
S> return ret;
S>}
S>
Здравствуйте, zelenprog, Вы писали:
S>>Скажем чтобы он мог сгенерировать для класса SomeClass S>>... глобальную функцию SomeClass_make() S>>... в которой параметры те-же, что и в методе Init() того же класса S>>а тело функции make примерно такое: S>>
S>>SomeClass_make(int param1, string param2)
S>>{
S>> SomeClass ret = new SomeClass;
S>> ret.Init(param1, param2);
S>> return ret;
S>>}
S>>
S>>Чтобы просто форвардить параметры в init
Z>Так это просто Фабрика?