2

プロデューサー/コンシューマー ベースのアプリケーションを設計していますが、プロデューサーによって生成されたタスクをクラス表現で表現することに行き詰まっています。

実際の問題は次のようになります。生産者はStandaloneTask、消費者が直接消費できる を生成できます。または、消費者が消費できる数に最初に抽出するCompressTask必要がある を生成できます。TaskDecompressorStandaloneTask

StandaloneTaskと の間には多くの共通点があるため、この共通情報をすべて含むCompressTaskと呼ばれる基本クラスを作成しました。TaskBase

class abstract TaskBase 
{

}

class StandloneTaskType1: TaskBase
{

}

class StandloneTaskType2: TaskBase
{

}

.
.
.

class StandloneTaskTypeN: TaskBase
{

}

タスクの解凍はどのように機能しますか? タスクには、実行時に入力する必要がある 1 つ以上のパラメーターを含めることができます。圧縮タスクは、パラメーターを含むタスクと、それらのパラメーターに入力する必要がある値を取得する方法に関するその他の情報で構成されます。値を取得した後、TaskDecompressorこれらすべての値をパラメーター化されたタスクに入力して、1 つ以上のスタンドアロン タスクを生成すると想定されます。

CompressTask以下のようなクラスを作成しました。

class CompressTask: TaskBase
{
    TaskBase task;

    //runtime parameters
}

CompressTaskさて、が から派生しTaskBase、 のインスタンスも含まれていることは、私には非常に奇妙に見えますTaskBase。そのようなクラスを持つことは正しいですか?または、特定のケースのより良いクラス表現がありますか。

4

4 に答える 4

3

全体として、この構造は珍しくありません。複合パターンの道をいくらか進み始めています。あなたCompressTaskはコンポジットのように振る舞い、あなたStandaloneTaskはリーフのように振る舞います。

その設計パターンを読んで、コンシューマーが TaskBase のサブクラスをCompressTaskまたはStandaloneTask. これにより、デザインが強化され、消費が簡素化されます。

于 2013-01-13T06:35:45.703 に答える
1

想像...

class Student: Person
{
    Person father;
    Person mother;
    Date dateOfEnrollment;
}

これは完全に理にかなっていますね。原則として、CompressTaskクラスに問題はありません。

于 2013-01-13T06:47:58.897 に答える
0

さらに良い... 想像してみてください...

class Foo // implicitly extends Object
{
    String name; // also a direct subclass of Object (at least in Java anyway)
    Integer age; // extends Number, which extends Object (at least in Javaland)
    Object theRootOfAllEvil; // a raw instance of the superclass
    int i; // the only member that is not an Object
}

私のジャワ語を許してください。しかし、私の出身地では何も問題はありません。

それはすべて、クラスの詳細に依存します。

于 2013-01-13T08:05:19.703 に答える
0

オブジェクト指向の重要な設計ルールの 1 つは、実装の継承よりも構成優先することです。多くの共通点があるからStandaloneTaskCompressTaskいって、それらが同じ基本クラスを共有できるようにするのは適切な選択ではありません。2 つのクラスがいくつかのインターフェイスを共有している場合は、インターフェイスの継承を使用してインターフェイスを除外することをお勧めします。2 つのクラスがいくつかの実装を共有している場合は、その実装をいくつかのクラスに分解し、それを上記の 2 つのクラス (つまり、構成)に埋め込むことをお勧めします。

あなたのケースに戻って、CompressTaskから派生しTaskBase、TaskBase のインスタンスも含まれています。これは、実装の継承と構成を同時に使用していることを意味しますが、これはあまり良くありません。次のスケルトンは参照用です。

interface Task
{
    // some common Task interface here...
}

class TaskImpl
// Or: class TaskImpl : Task // depends on your needs
{    
    // some common Task-related implementation here...
}

class CompressTask: Task // interface inheritance, NOT implementation inheritance
{
    TaskImpl taskImpl; // contains *reusable* task-related implementation
    Task task;  // contains the target task(s) to be compressed
    // other code...
}

class StandloneTaskType1: Task
{
    TaskImpl taskImpl;
    // other code...
}

.
.
.

class StandloneTaskTypeN: Task
{
    TaskImpl taskImpl;
    // other code...
}
于 2013-01-13T06:40:38.807 に答える