2

クラス Parameter があります。その目的は、特定のパラメーターが保持できる可能性のある値を表すことです (GetNumValues() と GetValue(int index) の 2 つの主要なメソッドを実装します)。

多くの場合、1 つの論理パラメーター (パラメーター値はビット フラグ) は、パラメーター クラスの 2 つ以上のインスタンス (つまり、1 または 2 のパラメーターと、4 または 8 のパラメーター) によって最適に表現されます。 5、6、9、または 10)。これを処理するには、パラメーターを含む CompositeParameter クラスを作成し、保持するパラメーターの組み合わせに基づいて GetNumValues() および GetValue() 関数を実装します。

また、CompositeParameter はパラメーターを組み合わせて 1 つのパラメーターとして機能させるため、「CompositeParameter はパラメーターである」という関係は理にかなっています。そのため、継承元のクラスのオブジェクトを構成するクラスがあるという状況に陥っていますが、これは正しくないようです。しかし同時に、より高いレベルのコードが CompositeParameters と Parameters をまったく同じに扱うことができない理由がわかりません。

私が考えることができる唯一のオプションは、CompositeParameter に単純にパラメーターを構成させることであり、より高いレベルのコードは CompositeParameters のみを処理します。ただし、これはやや無駄です。一般的なケースは、パラメーターを 1 つだけ含む 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 クラス (またはおそらく 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.

複合パターンのポイントは、Leaf オブジェクトが単純なケースを表し、Composite オブジェクトが複雑なケースを表し、クライアント コードが両方のケースを同じように処理できることです。インターフェイスでクライアント コードが 2 つを区別する必要がある場合、または基本クラスのコンポーネントを反復処理する必要がある場合は、パターンを使用しても実際には何の価値も得られません。

たとえば、主な関心事がテストである場合、基本クラスにメソッドを含めることができます。

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 に答える