Слишком много аргументов конструктора для шаблона внедрения зависимостей / наследования

Поэтому я решил использовать Factory Design Pattern вместе с Dependency Injection.

class ClassA
{
Object *a, *b, *c;
public:
ClassA(Object *a, Object *b, Object *c) :
a(a), b(b), c(c) {}
};

class ClassB : public ClassA
{
Object *d, *e, *f;
public:
ClassB(Object *a, Object *b, Object *c, Object *d, Object *e, Object *f) :
ClassA(a, b, c), d(d), e(e), f(f) {}
};

Теперь проблема в том, что classB имеет слишком много аргументов для конструктора. Это пример отдельного уровня наследования, но когда уровни наследования начинают становиться все глубже, и когда каждому классу слоя требуется построить больше объектов, конструктор в верхнем слое заканчивается, требуя слишком много аргументов, чтобы его можно было создать!

Я знаю, что мог бы использовать сеттеры вместо конструктора, но есть ли другой способ?

6

Решение

Сеттеры не рекомендуются для таких вещей, потому что они приводят к частично сконструированному объекту, который очень подвержен ошибкам. Распространенным шаблоном для построения объекта, который требует много параметров, является использование компоновщика. Ответственность ClassBBuilder заключается в создании объектов ClassB. Вы делаете конструктор ClassB частным и позволяете только строителю вызывать его, используя дружеские отношения. Теперь строитель может выглядеть как-то так

ClassBBuilder {
public:
ClassBBuilder& setPhoneNumber(const string&);
ClassBBuilder& setName(consg string&);
ClassBBuilder& setSurname(const string&);
ClassB* build();
}

И вы используете строитель нравится это:

ClassB* b = ClassBBuilder().setName('alice').setSurname('Smith').build();

Метод build () проверяет, что все обязательные параметры были установлены, и возвращает либо правильно сконструированный объект, либо NULL. Невозможно создать частично построенный объект. У вас все еще есть конструктор со многими аргументами, но он является закрытым и вызывается только в одном месте. Клиенты этого не увидят. Методы Builder также прекрасно документируют, что означает каждый параметр (когда вы видите ClassB (‘foo’, ‘bar’), вам нужно проверить конструктор, чтобы выяснить, какой параметр является именем, а какой фамилией).

6

Другие решения

Это одна из проблем C ++ (если это можно назвать проблемой). У него нет другого решения, кроме как сохранить минимальное количество параметров ctor.

Одним из подходов является использование структуры props, например:

struct PropsA
{
Object *a, *b, *c;
};

class ClassA
{
ClassA(PropsA &props, ... other params);
};

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

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

1

Я думаю, что то, что вы описываете, не является проблемой в C ++ — на самом деле, C ++ довольно хорошо отражает зависимости, выраженные вашим дизайном:

  1. Чтобы построить объект типа ClassAнужно три Object экземпляры (a, b а также c).
  2. Чтобы построить объект типа ClassBВам также нужно иметь три Object экземпляры (d, e а также f).
  3. Каждый объект типа ClassB можно рассматривать как объект типа ClassA,

Это означает, что для построения объекта типа ClassB вам нужно предоставить три Object объекты, которые необходимы для реализации ClassA интерфейс, а затем еще три для реализации ClassB интерфейс.

Я верю фактический вопрос здесь ваш дизайн. Вы можете рассмотреть различные подходы для решения этой проблемы:

  1. Не позволяй ClassB унаследовать ClassA, Может или не может быть вариант в зависимости от того, нужен ли вам однородный доступ к объектам любого типа (скажем, потому что у вас есть коллекция ClassA* и эта коллекция может также содержать указатели на ClassB).
  2. Ищите объекты, которые всегда появляются вместе. Как, может быть, первые два объекта передаются в любой конструктор (a а также b или же d а также e) представляют какую-то пару. Может быть, идентификатор объекта или тому подобное? В этом случае может быть полезно ввести для этого специальный реферат (читай: тип).
1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector