Twilight: Добрый день.
Постоянно сталкиваюсь со следующей проблемой: есть фабричный метод для создания объектов, в зависимости от некоторых условий, также есть некий набор входных данных, который нужно передать во вновь созданный объект.
Ниже псевдокод, описывающий текущее решение
class IObject
{
public:
virtual ~IObject() {}
virtual void initialize( const ObjectData &objectData ) = 0;
};
class AbstractObject : public IObject
{
public:
virtual void initialize( const ObjectData& objectData ) override
{
m_objectData = &objectData;
}
private:
ObjectData *m_objectData;
};
class ObjectA : public AbstractObject {};
class ObjectB : public AbstractObject {};
IObject* create( int type )
{
if( type == 1 ) return new ObjectA;
return newObjectB;
}
соответственно используется примерно так:
IObject *obj = create( type );
obj->initialize( objectData );
в целом, данный подход устраивает, если бы не одно НО: так как ObjectData передается не в конструктор, то внутри AbstractObject мне приходится держать не константную ссылку, как хотелось бы, а простой указатель. С одной стороны я знаю, что данный указатель получен из ссылки, и, таким образом, не может быть nullptr. Однако при разрастании кода, об этом можно забыть и все-таки влепить проверки из серии if( m_objectData ).
Альтернативный подход, который я вижу - это передача ObjectData в конструкторе:
class IObject
{
public:
virtual ~IObject() {}
};
class AbstractObject : public IObject
{
public:
AbstractObject( const ObjectData &objectData ) {}
};
class ObjectA : public AbstractObject
{
public:
ObjectA( const ObjectData &objectData ) : AbstractObject( objectData ) {}
};
class ObjectB : public AbstractObject
{
public:
ObjectB( const ObjectData &objectData ) : AbstractObject( objectData ) {}
};
IObject* create( int type, const ObjectData &objectData )
{
if( type == 1 ) return new ObjectA( objectData );
return new ObjectB( objectData );
}
Такой вариант меня не устраивает прежде всего тем, что в каждом наследуемом классе необходимо писать один и тот же код, для передачи ObjectData в базовый класс.
Т.е. получается, что для решения проблемы варианта 1 ( хранение указателя, вместо ссылки ) отлично подходит варинт 2, но с другой стороны он привносит необходимость прокидывания ObjectData через всю иерархию наследования, чего как раз нет в варианте 1.
Возможен ли "третий" вариант, в котором нет вышеперечисленных минусов?
https://forum.sources.ru/index.php?showtopic=419313&view=findpost&p=3835721