Re: "Гибкий" конструктор для инициализации объекта класса (аналог Dispose)
От: zelenprog  
Дата: 31.08.23 05:43
Оценка:
Z> ... бывают такие ситуации, когда конструктор не всегда может выделить необходимые ресурсы.
Z>Например, в момент создания объекта нет достаточной информации для "полноценного" создания объекта.
Z>Поэтому такие объекты приходится создавать в следующем порядке:
Z>1) Сначала нужно создать "пустой" объект, вызвать его конструктор. Объект создается, но пока не "захватывает" ресурсы. В таком состоянии объект не функционален.
Z>2) Затем нужно передать этому объекту необходимую информацию (установить значения его "ключевых" свойств), от которой зависит логика "захвата" ресурсов.
Z>3) И только теперь можно вызвать метод объекта, который выполнит захват ресурсов, назовем его InitializeResources().

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

Z>Получается, нужен какой-то "шаблон" для выделения ресурсов, аналогичный по схеме IDisposable, но противоположный по значению.
Z>Есть ли какие-либо шаблоны\методики\практики более "гибкого" выделения ресурсов в дополнение к конструктору класса?

Думаю лучше обсуждать на примере.
Вот упрощенный пример описываемой проблемы.

Простая программа читает список товаров и отображает их на форме.
Программа умеет работать с БД двух типов, у которых немного отличается структура и наименования полей. Соответственно для каждого типа БД нужен свой Адаптер.
Класс DBGoodsReader ("Читатель") не зависит от конкретной БД, он реализует общий алгоритм чтения товаров: сначала с помощью Адаптера извлекает данные, затем выполняет их некоторые преобразования ("подготовку" для отображения).

Получается, алгоритм такой:
1) Определяем тип БД
2) Создаем Адаптер, соответствующий типу БД
3) Передаем этот Адаптер классу "Читатель" (DBGoodsReader)
4) Читаем и отображаем данные.

Проблема в том, что конструкторы не

Class MainForm
{
    string mFileName;
    
    void OnButton_ReadDatabase()
    {
        T_DatabaseInfo lDatabaseInfo = new T_DatabaseInfo(mFileName);
        T_DBGoodsReader lDBGoodsReader = new T_DBGoodsReader;
        I_DBAdapter lDBAdapter = null;
        
        if lDatabaseInfo.DBType = Database.DBType1 then
            lDBAdapter = new T_DBAdapter1(mFileName);
        elseif lDatabaseInfo.DBType = Database.DBType2
            lDBAdapter = new T_DBAdapter2(mFileName);
        else
            // исключение "неизвестный тип БД
        endif
        
        lDBGoodsReader.SetAdapter(lAdapter);
        lDBGoodsReader.Init();
        lDBGoodsReader.Read();
        
        // показать на форме список товаров
    }
}


Напомню, что в конструктор невозможно передать параметры.
Приходится для "Читателя" cделать метод "SetAdapter", чтобы передать ему конкретный объект "Адаптер". И затем вызвать метод "Init".
Я читал, что это анти-паттерн. Но как сделать по другому?

Второй вопрос. Кто (какой объект) должен отвечать за проверку типа базы и создание конкретного Адаптера?
Сейчас это делается в Форме. Но по "теории" форма не должна ничего знать о таких "подробностях". Она должна просто использовать "Читателя".
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.