Составление объектов класса, от которого вы наследуете? - PullRequest
2 голосов
/ 04 февраля 2010

У меня есть класс Parameter, цель которого - представить возможные значения, которые может содержать определенный параметр (реализует два ключевых метода, GetNumValues ​​() и GetValue (int index)).

Часто один логический параметр (значения параметров представляют собой битовые флаги) лучше всего представить двумя или более экземплярами класса Parameter (то есть параметром, который может быть 1 или 2, и параметром, который может быть 4 или 8, а не одним Параметр чем может быть 5, 6, 9 или 10). Чтобы справиться с этим, я бы хотел создать класс CompositeParameter, который содержит параметры и будет реализовывать функции GetNumValues ​​() и GetValue () на основе комбинаций параметров, которые он содержит.

И поскольку CompositeParameter объединяет параметры, чтобы они действовали как один отдельный параметр, имеет смысл иметь отношение «CompositeParameter is a Parameter». Поэтому я нахожусь в ситуации, когда у меня есть класс, который составляет объекты класса, от которого он наследуется, что просто кажется неправильным. Но в то же время я не понимаю, почему код более высокого уровня не должен обрабатывать CompositeParameters и Parameters точно так же.

Единственный вариант, который я могу придумать, - это чтобы CompositeParameter просто составлял параметры, а код более высокого уровня работал бы только с CompositeParameters. Однако это несколько расточительно, так как в общем случае CompositeParameters будет содержать только один параметр.

Мысли

class Parameter
{
public:
    virtual unsigned int GetNumValues() const {...}
    virtual unsigned int GetValue(unsigned int index) const {...}
}

class CompositeParameter : public Parameter
{
public:
    // product of GetNumValues() of each item in mParamList
    virtual unsigned int GetNumValues() const {...} 

    // allow all the possible combinations of the items in mParamList to be
    // treated as one parameter. i.e. if mNumParams = 2, this would be analogous
    // to getting the row and col index of a matrix from index, and combining
    // the mParamList[0]->GetValue(row) and mParamList[1]->GetValue(col)
    virtual unsigned int GetValue(unsigned int index) const {...}

private:

    static const unsigned int MAX_PARAMS = 10;

    unsigned int mNumParams;
    const Parameter* mParamList[MAX_PARAMS];
}

Ответы [ 2 ]

2 голосов
/ 04 февраля 2010

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

Тогда вы можете иметь класс Parameter (или, возможно, класс ParameterImpl), который реализует параметр, а также класс CompositeParameter, который также реализует интерфейс параметра

1 голос
/ 04 февраля 2010
I have a class which composes objects of a class it inherits from,
which just doesn't seem right.

Разве это не определение композита?

(parameter values are bit flags)

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

Хорошо скрывать побитовые тесты за интерфейсом, но кажется, что наследование может быть излишним для решения проблемы с хорошо известными решениями в базовой информатике.


However, that is somewhat wasteful b/c the general case would be
CompositeParameters which contained just one Parameter.

Суть составного шаблона состоит в том, что объект Leaf представляет простой случай, объект Composite представляет сложный случай, и клиентский код может обрабатывать оба случая одинаково.Если вашему интерфейсу требуется, чтобы клиентский код различал эти два компонента или выполнял итерацию по компонентам базового класса, тогда вы на самом деле не получаете никакого значения от использования шаблона.

Например, если ваша основная задача -тестируя, тогда базовый класс может иметь метод:

bool Test() const;

Конечная реализация класса будет выглядеть следующим образом:

bool LeafTester::Test() { return _DoTest(); }

Реализация составного класса будет выглядеть следующим образом:

bool CompositeTester::Test() {
    bool success = true;

    for (int i = 0; i < m_count; i++)
        success &= m_components[i].Test();

    return success;
}

И клиенты всегда будут использовать такой код:

// tester could be a Composite or a leaf, but we don't care:
bool testResult = tester.Test();

Я использовал цикл for, чтобы сделать пример простым.На практике я бы использовал STL.

...