3

ドメインレイヤーオブジェクトをUIオブジェクトに、またはその逆に変換するために使用されるオブジェクト変換クラスを作成しています。問題は、UI オブジェクトが階層に編成されているため、オブジェクト変換クラスに「instanceof」ステートメントが含まれていることです。ここには明確なコードの匂いがありますが、解決策が何であるかはわかりません。

したがって、私の UI 階層には、次のように RuleDTO が含まれています。

public class RuleDTO {
    protected long ruleID;
    protected long rowID;   
    protected AttributeDTO leftCondition;
    protected AttributeDTO rightCondition;
    protected OperationTypeDTO operationType; 
    protected boolean isActive;     
    // etc...
}

私の RuleDTO は、次のように AssignmentRuleDTO によってサブクラス化できます。

public class AssignmentRuleDTO extends RuleDTO {
    protected String assignedToTeam;
    protected String assignmentOperator;        
    // etc...
}

RuleDTO は EvaluationRuleDTO によってサブクラス化することもできます。

public class EvaluationRuleDTO extends RuleDTO {
    protected String successAction;
    protected String failureAction;
    // etc...
}

問題は、次のタイプのロジックを含む ObjectConversionHelper クラスで発生します。

{
    // Perform logic common to RuleDTO such as setting ruleID, isActive etc
    if(ruleDTO instanceof AssignmentRuleDTO) {
        // Set assignedToTeam and assignmentOperator etc
    }
    else if (ruleDTO instanceOf EvaluationRuleDTO) {
        // Set successAction and failureAction etc  
    }
}

代わりに、ここで良い解決策は何でしょうか? 訪問者パターンについて読んだことがありますが、ここでどのように適用されるかわかりません。

ありがとう

4

7 に答える 7

3

ここでは Visitor パターンを使用するのが妥当なアプローチだと思います。つまり、Visitor インターフェースができます。

interface RuleDTO {
    void visit(RuleDTO theRule);
    void visit(EvaluationRuleDTO theEval);
    void visit(AssignmentRuleDTO theAssign);
    ... and so on ...
}

そして、これらの具象クラスにメソッドを追加して、二重ディスパッチを処理します

public void accept(RuleDTOVisitor theVisitor) {
    theVisitor.visit(this);
}

最後に、SettingPropertiesVisitor などのビジターを実装するクラスを作成します。メソッドごとに、アプリケーションの要件に応じて各オブジェクトの適切なフィールドが設定される実装を行うことができます。

じゃあそれを使うには

aRuleDTO.accept(new SettingPropertiesVisitor());

このようにして、タイプごとに適切なビジター メソッドが呼び出され、SettingPropertiesVisitor のメソッド内で適切な割り当てを行うことができます。これにより、instanceof チェックが回避され、セッター ロジックがオブジェクトから分離されます。

もちろん、これがあなたが作成した唯一の訪問者である場合、それはやり過ぎかもしれません。その場合、instanceof は子猫を殺すようなものではありません。しかし、ここでの明らかな欠点は、API を拡張するたびに、ビジター インターフェイスを変更する必要があり、おそらくすべての具体的なビジターが新しいメソッドをサポートする必要があることです。

于 2012-07-18T20:55:37.977 に答える
3

クラスRuleDTOには、呼び出されるメソッドsetStuff()または同様のメソッドが必要です。

次に、それをオーバーライドしてAssignmentRuleDTOEvaluationRuleDTO関連するフィールドを設定します。

このようにして、あなたObjectConversionHelperはただ呼び出すことができます

ruleDTO.setStuff();
于 2012-07-18T20:28:35.790 に答える
2

ビジターは、ここではやり過ぎのように見えます。

オブジェクトのグラフに対する反復はありません。
二重発送の必要はありません。

KISSとYAGNIを思い出してください。抽象メソッドを追加するか、そのままにしておきます。
後でいつでもリファクタリングできます-テストが整っていると仮定します;)

于 2012-07-18T23:28:38.440 に答える
1

あなたの場合、RuleDTO に convertToOtherClass メソッドを記述してビジター パターンを適用できます。これは、そのサブクラスによってオーバーライドされます。次に、オブジェクト変換クラスに、convertRuleDTO の行に沿ったメソッド (RuleDTO の convertToOtherClass メソッドで呼び出される) があり、関連するコードを実行し、サブクラスではない RuleDTO のインスタンスで動作していることを認識して保護します。そうしないと、サブクラスが convertToOtherClass メソッドをオーバーライドするためです。

于 2012-07-18T20:29:30.000 に答える
0

DTO クラスごとに 1 つの ObjectConversionHelper クラスを作成するのはどうですか? それらのそれぞれは、共通の変換インターフェイスを異なる方法で実装し、継承されたメンバーなどを呼び出すことができます。その後、DTO に関連するヘルパーを作成するオブジェクト作成ファクトリを利用できます (つまり、リフレクション メカニズムを使用)。

于 2012-07-20T08:49:03.357 に答える
0

もっともらしいアプローチがいくつかあります。私が検討する2つは、すべてのクラスが実装するインターフェースを使用するか、さまざまなクラスに対応する列挙型を使用することです。

インターフェースがある場合(それを と呼びましょうpublic interface DTO、その中にメソッドシグネチャを呼び出すsetFields()か、実装するクラスのそれぞれが実装する必要がある同様のものを含めることができます。次に、ポリモーフィズムの魔法により、すべてのオブジェクトDTOを型キャストを使用するものとして扱うことができますsetFields()実際のオブジェクトが何であるかを気にせずにそれらを呼び出す.setFields()個々のクラスのそれぞれのメソッドがそれを処理します.

または、本質的に各クラスの ID である列挙型を作成し、各クラスにその型のグローバル変数 (getter と setter を完備) を持たせて、それを識別することができます。これはやや「ハック」な回避策ですが、それでも実行可能な回避策です。

于 2012-07-18T20:51:11.097 に答える
0

"else" を取り出してください... 何が問題なのですか?

于 2012-07-18T20:28:13.577 に答える