「デザイン・モード」--ビジター・モード


ビジターモード
参考:『JAVAとモード』の訪問者モード
  • ビジターモード
  • 認識
  • 思考
  • 使用シーン
  • メリットとデメリット
  • UML図
  • コード実装

  • と知り合いになる
    ビジターモードは、オブジェクトの動作モードです.アクセス者モードの目的は、あるデータ構造要素に適用されるいくつかの動作をカプセル化することである.これらの操作を修正する必要がある場合、この操作を受け入れるデータ構造は変わらないことができる.変化するのは訪問者で、変わらないのは被訪問者です
    考える
    本質は:通路を予約し、コールバックを実現する
    条件付き受信アクセス、条件を満たさない場合はアクセス禁止
    シーンの操作
  • オブジェクトの構造は変動が少ない、オブジェクトに対する操作が常に変化する場合はパッケージング操作でアクセス者モード
  • を使用することができる.
  • オブジェクト構造の各要素に対して異なる操作がある場合、各要素に異なる操作をカプセル化してアクセス者モード
  • を用いることができる.
    メリットとデメリット
  • の利点
  • の優れた拡張性:オブジェクト構造の要素を変更せずに、オブジェクト構造の要素に新しい機能を追加することができます.
  • の良好な多重化:オブジェクト構造全体に共通する機能をアクセス者によって定義することができ、多重化の程度を向上させることができる.
  • 分離無関係行為:訪問者によって無関係行為を分離することができ、関連行為をカプセル化し、訪問者を構成することができ、このように各訪問者の機能は比較的単一である.

  • の欠点
  • オブジェクト構造の変化は困難である:オブジェクト構造が変化し、アクセス者のインタフェースとアクセス者の実現に相応の変化が発生し、代価が高すぎる
  • はカプセル化を破壊する:訪問者モードは通常、オブジェクト構造が訪問者とObjectStructrueに内部データを開放する必要があり、これはオブジェクトのカプセル化性を破壊する.


  • UML図
    データ構造の各ノードは、1つのアクセス者の呼び出しを受け入れることができ、ノードはアクセス者オブジェクトにノードオブジェクトを転送し、アクセス者オブジェクトは逆にノードオブジェクトの操作を実行します.このような過程を「二重派閥」と呼ぶ.ノードは、アクセス者を呼び出し、それ自体を転送し、アクセス者は、転送されたノードオブジェクトを介してノードに関する操作を実行します.ビジター・モードの概略クラス図を次に示します.
  • 抽象ビジター(Visitor)ロール:1つ以上のメソッド操作が宣言され、すべての特定のビジターロールが実装する必要があるインタフェースが形成されます.
  • 特定のアクセス者(ConcreteVisitor)ロール:抽象アクセス者が宣言したインタフェース、すなわち抽象アクセス者が宣言した各アクセス操作を実現します.
  • 抽象ノード(Node)ロール:パラメータとしてアクセス者オブジェクトを受け入れる承認アクションを宣言します.
  • 特定のノード(ConcreteNode)ロール:抽象ノードによって規定された受け入れ操作を実現します.
  • 構造オブジェクト(ObjectStructure)ロール:構造内のすべての要素を遍歴できる責任があります.必要に応じて、アクセス者オブジェクトが各要素にアクセスできるように、高レベルのインタフェースを提供します.必要に応じて、リストやSetなどの複合オブジェクトまたは集約に設計できます.

  • 実行シーケンス図
    コード実装
    //     ,              
    public interface Visitor {
        //   NodeA     
        public void visit(NodeA node);
        //   NodeB     
        public void visit(NodeB node);
    }
    
    //     
    public class VisitorA implements Visitor {
        //   NodeA     
        @Override
        public void visit(NodeA node) {
            System.out.println(node.operationA());
        }
        //   NodeB     
        @Override
        public void visit(NodeB node) {
            System.out.println(node.operationB());
        }
    }
    //     
    public class VisitorB implements Visitor {
        //   NodeA     
        @Override
        public void visit(NodeA node) {
            System.out.println(node.operationA());
        }
        //   NodeB     
        @Override
        public void visit(NodeB node) {
            System.out.println(node.operationB());
        }
    }
    //    
    public abstract class Node {
        //    
        public abstract void accept(Visitor visitor);
    }
    //     NodeA
    public class NodeA extends Node{
        //     
        @Override
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }
        //NodeA     
        public String operationA(){
            return "NodeA";
        }
    }
    //     NodeB
    public class NodeB extends Node{
       //     
        @Override
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }
        // NodeB     
        public String operationB(){
            return "NodeB";
        }
    }
    //       ,              ,      add()            。        ,             。
    public class ObjectStructure {
        //    
        private List nodes = new ArrayList();
    
        //         
        public void action(Visitor visitor){
    
            for(Node node : nodes)
            {
                node.accept(visitor);
            }
    
        }
        //          
        public void add(Node node){
            nodes.add(node);
        }
    }
    //   
    public class Client {
    
        public static void main(String[] args) {
            //        
            ObjectStructure os = new ObjectStructure();
            //         
            os.add(new NodeA());
            //         
            os.add(new NodeB());
            //       
            Visitor visitor = new VisitorA();
            os.action(visitor);
        }
    }