2010-02-03 86 views
2

我有一个类参数,其目的是为了表示某个参数可以容纳的可能值(实现两个关键方法,GetNumValues()和GetValue(int index))。撰写您继承的类的对象?

通常一个逻辑参数(参数值是位标志)最好由2个或更多的Parameter类实例表示(即参数可以是1或2,参数可以是4或8,而不是一个参数可以是5,6,9或10)。为了处理这个问题,我想创建一个包含Parameters的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]; 
} 
+1

在谈论C++代码时,使用C++代码而不是英语来描述问题几乎总是比较好的。 – 2010-02-03 23:12:45

回答

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。

+0

这是组合的定义,我的问题是它是从它正在编写的同一个东西继承而来的。 我的目标不是隐藏按位测试,而是为了测试目的创建一些能够生成所有可能值的东西。这是GetValue(...)的结果,将用于按位测试。 我只是使用名称参数来说明,我真正的问题是关于组成/继承设计。 – Chris 2010-02-04 00:28:01

+0

组合的定义是它继承了它与它组合的相同事物。请参阅“设计模式”pp164。如果这就是你的组合所做的,那么它就遵循这个模式。 – richj 2010-02-04 09:33:20

+0

根据模式,Composite和Leaf都来自抽象基类Component。所以如果你想按照本书所描述的方式来实现这个模式,参数将是抽象的,你需要第二个子类LeafParameter。 – richj 2010-02-04 09:42:29

2

这似乎是一个完全合理的设计。我所做的唯一改变是将参数从一个类改为一个接口。

然后你可以有一个参数类(或者一个ParameterImpl类)实现的参数,也有CompositeParameter类,也实现了参数接口

+0

因此,CompositeParameter将实现Parameter接口并包含ParameterImpl对象? – Chris 2010-02-03 23:33:02

+0

是的,那个或任何实现了参数接口的对象 – 2010-02-03 23:35:41