23デザインパターン第16章:Java訪問者パターン
定義:特定のデータ構造の各要素に作用する特定の操作をカプセル化します。データ構造を変更せずに、これらの要素に作用する新しい操作を定義できます。
タイプ:行動パターン
クラス図:
ビジターモードは、行動モードの中で最も複雑なモードかもしれませんが、これが私たちがそれを習得しない理由ではありません。
まず、簡単な例を見てみましょう。コードは次のとおりです
class A {public void method1(){system.out.println( "I a a"); } public void method2(b b){b.showa(this); }} class B {public void showa(a){a.method1(); }}主に、クラスAのメソッドMethod1とMethod Method2の違いを見てみましょう。メソッドMethod1は非常に単純です。文「I Am a」を印刷するだけです。メソッドメソッド2はもう少し複雑です。クラスBをパラメーターとして使用し、クラスBのshowaメソッドを呼び出します。
クラスBのshowaメソッドを見てみましょう。ShowaメソッドはクラスAをパラメーターとして使用し、クラスAのMethod1メソッドを呼び出します。Method2メソッドは、独自のMethod1メソッドを呼び出していることがわかります。その実行結果も「I Am」でなければなりません。分析後、これら2つの方法を実行して、実行の結果を確認しましょう。
public class test {public static void main(string [] args){a a = new a(); a.method1(); a.method2(new b()); }}実行中の結果は次のとおりです。
私はです
私はです
この例を理解した後、訪問者パターンの90%を理解します。この例では、クラスAの場合、クラスBは訪問者です。ただし、この例は訪問者モード全体ではありません。直感的ですが、スケーラビリティが低いです。訪問者モードの一般的な実装について話しましょう。クラス図を通して、訪問者モードでは、次の役割が主に含まれていることがわかります。
抽象訪問者:訪問者がアクセスできる要素を宣言する抽象クラスまたはインターフェイス。具体的には、プログラムでは、Visitメソッドのパラメーターは、どのオブジェクトにアクセスできるかを定義します。
訪問者:抽象的な訪問者によって宣言された方法を実装します。これは、訪問者がすべきこと、クラスにアクセスした後に何をすべきかに影響します。
抽象要素クラス:どのタイプの訪問者アクセスが受け入れられるかを宣言するインターフェイスまたは抽象クラス。このプログラムは、Acceptメソッドのパラメーターを使用して定義されます。一般に、抽象要素には2種類の方法があります。1つは独自のビジネスロジックであり、もう1つはどのタイプの訪問者がアクセスできるかです。
要素クラス:抽象要素クラス、通常はvisitor.visit(this)によって宣言された受け入れメソッドを実装し、基本的に固定式を形成しました。
構造オブジェクト:要素コンテナには、一般に、リスト、セット、マップなどの複数の異なるクラスとインターフェイスに対応するコンテナが含まれています。この役割は、プロジェクトではめったに抽象化されません。
訪問者モードの一般的なコード実装
抽象クラス要素{public Abstract void Accept(Ivisitor Visitor); public abstract void dosomething(); } interface ivisitor {public void visit(concreteElement1 el1);パブリックボイド訪問(concreteElement2 el2); } class concreteElement1 extends element {public void dosomething(){system.out.println( "これは要素1"); } public void Accept(ivisitor Visitor){visitor.visit(this); }} class concreteElement2拡張element {public void dosomething(){system.out.println( "これは要素2"); } public void Accept(ivisitor Visitor){visitor.visit(this); }}クラスの訪問者はivisitor {public void visit(concreteelement1 el1){el1.dosomething(); } public void Visit(concreteElement2 el2){el2.dosomething(); }} class objectStruture {public static list <element> getList(){list <element> list = new ArrayList <element>();ランダムran = new Random(); for(int i = 0; i <10; i ++){int a = ran.nextint(100); if(a> 50){list.add(new ConcreteElement1()); } else {list.add(new ConcreteElement2()); }} return list; }} public class client {public static void main(string [] args){list <element> list = objectStruture.getList(); for(要素E:list){e.accept(new Visitor()); }}}訪問者モードの利点
単一の責任の原則に従う:訪問者モードが適用されるシナリオでは、要素クラスの訪問者にカプセル化する必要がある操作は、要素クラス自体とはほとんど関係がなく、揮発性のある操作でなければなりません。一方では、訪問者モードの使用は単一の責任の原則に準拠しており、他方では、カプセル化された操作が通常揮発性であるため、変更が発生すると、要素クラス自体を変更せずに変更部品の拡張を達成できます。
優れたスケーラビリティ:要素クラスは、さまざまな訪問者を受け入れることで異なる操作を拡張できます。
訪問者モードに適用されるシナリオ
オブジェクトにオブジェクトに関連していない(または弱く関連する)操作があり、これらの操作がオブジェクトを汚染するのを避けるために、訪問者モードを使用してこれらの操作を訪問者にカプセル化することができます。
オブジェクトのグループに同様の操作がある場合、多数の重複コードを回避するために、これらの重複操作を訪問者にカプセル化することもできます。
ただし、ビジターモードはそれほど完璧ではなく、致命的な欠陥もあります。新しい要素クラスを追加することはより困難です。訪問者パターンのコードを通じて、訪問者クラスでは、各要素クラスに対応する処理方法があることがわかります。つまり、各要素クラスを追加するには、訪問者クラス(訪問者クラスのサブクラスまたは実装クラスも含まれます)を変更する必要があります。つまり、要素クラスの数が不確かな場合、訪問者モードに注意して使用する必要があります。したがって、訪問者モードは、既存の機能のリファクタリングにより適しています。たとえば、プロジェクトの基本的な機能が決定されている場合、要素クラスのデータは基本的に決定されており、変更されません。変更されるのは、これらの要素内の関連する操作だけです。この時点で、Visitorモードを使用して元のコードをリファクタリングして、各要素クラスを変更せずに元の機能を変更できるようにすることができます。
要約します
Design Patternの著者であるGOFは、訪問者モードについて説明しています。ほとんどの場合、訪問者モードを使用する必要がありますが、必要になると、本当に必要です。もちろん、これは本当の大物のためだけです。現実には(少なくとも私がいる環境では)、多くの人々はしばしば設計パターンに夢中になっています。デザインパターンを使用する場合、使用しているパターンがこのシナリオに適しているかどうかを真剣に検討することはありませんが、オブジェクト指向のデザインを制御する能力を示したいだけです。プログラミング時にこのメンタリティがある場合は、デザインパターンを悪用することがよくあります。したがって、設計パターンを学習する場合、パターンの適用性を理解する必要があります。パターンを使用することは、その利点を理解しているため、パターンを使用する必要があります。パターンを使用しないでください。パターンを使用するのではなく、その欠点を理解していないため、その利点を理解していないためパターンを使用しないようにします。
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。