2

我有一个类 Parameter,其目的是表示某个参数可以包含的可能值(实现两个关键方法,GetNumValues() 和 GetValue(int index))。

通常一个逻辑参数(参数值是位标志)最好由 Parameter 类的 2 个或多个实例表示(即一个 Parameter 可以是 1 或 2,一个 Parameter than 可以是 4 或 8,而不是一个 Parameter than can为 5、6、9 或 10)。为了解决这个问题,我想创建一个包含参数的 CompositeParameter 类,并将根据它所拥有的参数组合实现 GetNumValues() 和 GetValue() 函数。

并且由于 CompositeParameter 正在组合参数以使它们充当单个参数,因此“CompositeParameter 是一个参数”关系是有意义的。所以我发现自己的情况是,我有一个类,它组成了它继承自的类的对象,这似乎不正确。但与此同时,我不明白为什么更高级别的代码不能将 CompositeParameters 和 Parameters 完全相同。

我能想到的唯一选择是让 CompositeParameter 简单地组合参数,而更高级别的代码只会处理 CompositeParameters。但是,这有点浪费 b/c,一般情况下 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];
}
4

2 回答 2

2

这似乎是一个非常合理的设计。我要做的唯一更改是将 Parameter 从类更改为接口。

然后你可以有一个实现 Parameter 的 Parameter 类(或者可能是 ParameterImpl 类),并且还有一个也实现 Parameter 接口的 CompositeParameter 类

于 2010-02-03T23:15:58.287 回答
1
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.

复合模式的要点是,一个叶子对象代表简单的情况,一个复合对象代表复杂的情况,客户端代码可以同等对待这两种情况。如果您的界面需要客户端代码来区分两者,或者遍历基类组件,那么您并没有真正从使用该模式中获得任何价值。

例如,如果您主要关心的是测试,那么基类可能有一个方法:

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。

于 2010-02-03T23:49:07.810 回答