デザインパターン二十から一:ビジターパターン(ビジター)

実生活では、オブジェクトのコレクションでは、異なる要素の数に存在し、各要素別の訪問者とハンドリングの様々なものがあります。例えば、公園内のいくつかのアトラクションがあり、多くの観光客があり、同じアトラクションの異なる評価の観光客が異なっていてもよい。病院の医師の処方薬は、さまざまな要素が含まれ、その指定された価格と薬局のスタッフメンバーを見ますそのアプローチは、メンバーが処方箋の内容に基づいて処方を埋めるために処方数以上、薬局のスタッフに基づいて価格マーク名の薬を、指定された、異なっています。

多くのそのような例は、たとえば、映画やテレビ番組の中の文字は、異なる観客の評価は、彼らが異なっている、ありますが、そこに買い物商品の「買い物かご」の顧客、主に選択された製品に関する顧客がお金の価値、そして心配キャッシャーは、商品の価格と数量です。

これらのデータ要素は、比較的安定的かつアクセスして、さまざまな処理されたデータ構造より便利な「ビジターモード」で処理された場合は、。ビジターパターン処理方法は、データ構造から分離することができ、必要に応じて、新たな処理方法を追加することができ、およびプログラムのスケーラビリティと柔軟性を向上させ、元のプログラムコードやデータ構造を変更しないでください。

モデルの定義と特性

訪問者の定義を(ビジター)モード:各操作要素の新しい分離操作は、特定のデータ構造に適用されるが、それは、これらの要素に作用するの前提の下で、データの構造を変更することなく追加することができるように、別々のカテゴリにそれらをカプセル化各要素のデータ構造にアクセスするためのさまざまな方法を提供します。行動が最も複雑なモデルベースのモードで、データ構造データの操作で分離されます。

次のように訪問者(ビジター)モデルは、オブジェクトの行動パターンであり、その主な利点です。

  1. グッドスケーラビリティ。構造要素オブジェクトを変更せずに、オブジェクト構造要素に新しい機能を追加可能です。
  2. グッド再利用。全体の目的は、それによって、システムの多重度を増加させる、構造的特徴共通の訪問者が定義することができます。
  3. 優れた柔軟性。訪問者モードのデータ構造は、操作がシステムデータ構造の進化に影響を与えることなく、比較的自由に設定することができるように、デカップリング構造の操作に適用されます。
  4. 単一責任の原則に沿って。一緒にパッケージビジターパターンに関連する動作は、すべての訪問者の機能は、比較的単純であるように、訪問者が構成されています。


訪問者(ビジター)モードの主な欠点は次の通りです。

  1. クラスは困難である新しい要素を追加します。ビジター・モードでは、各新しい要素タイプは、に反して特定のビジター各クラスの特定の動作に対応する増加有する「オンオフ原理」を
  2. カプセル化に違反します。訪問者の公表内容のビジターパターンの特定の要素、このブレークカプセル化オブジェクト。
  3. 依存関係逆転の原則に違反します。抽象クラスに依存している特定のカテゴリに依存ではなく、Visitorパターン。

アーキテクチャと実装モデル

主な訪問者(ビジター)モードでは、次のように基本的な構造及び方法があり、別々のクラスに別々のパッケージに作用する操作子を達成する方法です。

1.構造モデル

Visitorパターンは、次の主要な役割で構成されています。

  1. 抽象ビジター(訪問者)の役割:特定のアクセス動作要素訪問()に対応するクラスごとに、特定の要素にアクセスするためのインタフェースを定義し、動作パラメータの識別の種類特定の要素がアクセスされます。
  2. 具体的な訪問者(ConcreteVisitor)役割:来場者の抽象的役割は、訪問者が要素にアクセスしたときにどうするかを決定するために、各アクセス動作で宣言されました。
  3. 抽象要素(エレメント)の役割:インタフェースを含む宣言は(受け入れ動作受け付け)、及びパラメータ()メソッドを受け入れるように訪問者のオブジェクトを受け入れました。
  4. 詳細な要素(ConcreteElement)役割:抽象文字要素は、それが特異的に関連する要素は、サービス論理演算そのものを含んでいてもよいが、通常その方法visitor.visit(本)である()操作を受け付けました。
  5. オブジェクト構造(オブジェクト構造体)の役割:役割はコンテナの方法でオブジェクトを横断する訪問者のためのすべての要素を提供含むコンテナ要素は通常、リスト、セット、マップと他の重合クラスによって実装されています。


図1に示す構造。
 

                        図訪問者構造(ビジター)モード
 

実現の2モード

Visitorパターンの実装コードは次のよう:

package visitor;
import java.util.*;
public class VisitorPattern
{
    public static void main(String[] args)
    {
        ObjectStructure os=new ObjectStructure();
        os.add(new ConcreteElementA());
        os.add(new ConcreteElementB());
        Visitor visitor=new ConcreteVisitorA();
        os.accept(visitor);
        System.out.println("------------------------");
        visitor=new ConcreteVisitorB();
        os.accept(visitor);
    }
}
//抽象访问者
interface Visitor
{
    void visit(ConcreteElementA element);
    void visit(ConcreteElementB element);
}
//具体访问者A类
class ConcreteVisitorA implements Visitor
{
    public void visit(ConcreteElementA element)
    {
        System.out.println("具体访问者A访问-->"+element.operationA());
    }
    public void visit(ConcreteElementB element)
    {
        System.out.println("具体访问者A访问-->"+element.operationB());
    }
}
//具体访问者B类
class ConcreteVisitorB implements Visitor
{
    public void visit(ConcreteElementA element)
    {
        System.out.println("具体访问者B访问-->"+element.operationA());
    }
    public void visit(ConcreteElementB element)
    {
        System.out.println("具体访问者B访问-->"+element.operationB());
    }
}
//抽象元素类
interface Element
{
    void accept(Visitor visitor);
}
//具体元素A类
class ConcreteElementA implements Element
{
    public void accept(Visitor visitor)
    {
        visitor.visit(this);
    }
    public String operationA()
    {
        return "具体元素A的操作。";
    }
}
//具体元素B类
class ConcreteElementB implements Element
{
    public void accept(Visitor visitor)
    {
        visitor.visit(this);
    }
    public String operationB()
    {
        return "具体元素B的操作。";
    }
}
//对象结构角色
class ObjectStructure
{   
    private List<Element> list=new ArrayList<Element>();   
    public void accept(Visitor visitor)
    {
        Iterator<Element> i=list.iterator();
        while(i.hasNext())
        {
            ((Element) i.next()).accept(visitor);
        }      
    }
    public void add(Element element)
    {
        list.add(element);
    }
    public void remove(Element element)
    {
        list.remove(element);
    }
}

次のようにプログラムの動作結果は以下のとおりです。 

具体访问者A访问-->具体元素A的操作。
具体访问者A访问-->具体元素B的操作。
------------------------
具体访问者B访问-->具体元素A的操作。
具体访问者B访问-->具体元素B的操作。

応用例のモード

[実施例1]「ビジター(訪問)モード「アナログ・アーツと鋳造当社の機能を使用して。

分析:「銅」の彫像を使って芸術は絵を描くことができ、「紙」を使用して、考案することができ、ミントの使用「銅」のコインを印刷することができ、請求書を印刷することができ、「紙」を使用して。「銅」とこれら二つの要素の「紙」の例は、使用ビジターパターンに適し達成するために、メソッドを処理する二つの異なる企業。

まず、抽象の訪問者である会社(会社)インタフェースの定義、これら二つの要素の紙での作品(紙)や銅(CUPRUM)を作成するための2つのメソッドを提供し、再定義アーツ(ArtCompany)クラスと造語特定の訪問者がある会社(ミント)クラス、実装親インターフェースの方法;次いで、材料を定義する抽象要素である(材料)インターフェースは、訪問者(会社)オブジェクトを受信するための方法(会社訪問者)を受け入れる提供しましたアクセス、特定の要素型で再定義紙(紙)クラス及び銅(CUPRUM)クラス、実装親インターフェースのメソッド;最後に、ロールの目的である集電体の材料を定義する(SetMaterial)クラスは、すべて保存しています容器(会社ビジター)メソッドのすべての要素を受け入れるオブジェクトを横断への訪問者を提供するコンテナ要素のリスト、及び、材料セット(SetMaterial)を提供するプログラムを形成するように設計された顧客のカテゴリは、訪問者(会社)オブジェクトアクセスオブジェクトItemListenerは、ユーザーの要求を処理するインターフェース、イベントを実装します。図2は、構成図です。
 

                 芸術と鋳造会社の構造チャート


コードは以下の通りであります:

package visitor;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class VisitorProducer
{
    public static void main(String[] args)
    {
        new MaterialWin();       
    }
}
//窗体类
class MaterialWin extends JFrame implements ItemListener
{
    private static final long serialVersionUID=1L;   
    JPanel CenterJP;
    SetMaterial os;    //材料集对象
    Company visitor1,visitor2;    //访问者对象
    String[] select;
    MaterialWin()
    {
        super("利用访问者模式设计艺术公司和造币公司");
        JRadioButton Art;
        JRadioButton mint;           
        os=new SetMaterial();     
        os.add(new Cuprum());
        os.add(new Paper());
        visitor1=new ArtCompany();//艺术公司
        visitor2=new Mint(); //造币公司      
        this.setBounds(10,10,750,350);            
        this.setResizable(false);       
        CenterJP=new JPanel();       
        this.add("Center",CenterJP);      
        JPanel SouthJP=new JPanel();
        JLabel yl=new JLabel("原材料有:铜和纸,请选择生产公司:");
        Art=new JRadioButton("艺术公司",true);
        mint=new JRadioButton("造币公司");
        Art.addItemListener(this);
        mint.addItemListener(this);       
        ButtonGroup group=new ButtonGroup();
        group.add(Art);
        group.add(mint);
        SouthJP.add(yl);
        SouthJP.add(Art);
        SouthJP.add(mint);
        this.add("South",SouthJP);       
        select=(os.accept(visitor1)).split(" ");    //获取产品名
        showPicture(select[0],select[1]);    //显示产品
    }
    //显示图片
    void showPicture(String Cuprum,String paper)
    {
        CenterJP.removeAll();    //清除面板内容
        CenterJP.repaint();    //刷新屏幕
        String FileName1="src/visitor/Picture/"+Cuprum+".jpg";
        String FileName2="src/visitor/Picture/"+paper+".jpg";
        JLabel lb=new JLabel(new ImageIcon(FileName1),JLabel.CENTER);
        JLabel rb=new JLabel(new ImageIcon(FileName2),JLabel.CENTER);
        CenterJP.add(lb);
        CenterJP.add(rb);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);            
    }
    @Override
    public void itemStateChanged(ItemEvent arg0)
    {
        JRadioButton jc=(JRadioButton) arg0.getSource();
        if (jc.isSelected())
        {
            if (jc.getText()=="造币公司")
            {
                select=(os.accept(visitor2)).split(" ");
            }
            else
            {            
                select=(os.accept(visitor1)).split(" ");
            }
            showPicture(select[0],select[1]);    //显示选择的产品
        }    
    }
}
//抽象访问者:公司
interface Company
{
    String create(Paper element);
    String create(Cuprum element);
}
//具体访问者:艺术公司
class ArtCompany implements Company
{
    public String create(Paper element)
    {
        return "讲学图";
    }
    public String create(Cuprum element)
    {
        return "朱熹铜像";
    }
}
//具体访问者:造币公司
class Mint implements Company
{
    public String create(Paper element)
    {
        return "纸币";
    }
    public String create(Cuprum element)
    {
        return "铜币";
    }
}
//抽象元素:材料
interface Material
{
    String accept(Company visitor);
}
//具体元素:纸
class Paper implements Material
{
    public String accept(Company visitor)
    {
        return(visitor.create(this));
    }
}
//具体元素:铜
class Cuprum implements Material
{
    public String accept(Company visitor)
    {
        return(visitor.create(this));
    }
}
//对象结构角色:材料集
class SetMaterial
{   
    private List<Material> list=new ArrayList<Material>();   
    public String accept(Company visitor)
    {
        Iterator<Material> i=list.iterator();
        String tmp="";
        while(i.hasNext())
        {
            tmp+=((Material) i.next()).accept(visitor)+" ";
        }
        return tmp; //返回某公司的作品集     
    }
    public void add(Material element)
    {
        list.add(element);
    }
    public void remove(Material element)
    {
        list.remove(element);
    }
}

図3に示すプログラムの結果。
 

      アート、設計された製品
(A)アート-設計された製品

 

         ミントはお金を生成しました

 

シーンモードの応用

一般の訪問者(ビジター)モードの場合に考慮することができます。

  1. オブジェクトの構造は比較的安定しているが、頻繁に動作アルゴリズムのプログラムを変更します。
  2. オブジェクトのオブジェクト構造が異なる、関係のないさまざまな操作を提供する必要があるが、また、これらの変更は、オブジェクト構造体の動作に影響を与える避けるために。
  3. オブジェクト構造は、オブジェクトの多くの種類が含まれ、これらのオブジェクトの望ましい実施形態のいくつかは、その動作の特定のタイプに依存します。

拡張モード

訪問者(ビジター)モデルは、一種類の頻繁に使用されているデザインパターンは、それが、多くの場合、2つのデザインパターンの使用に関連しています。

(1)「反復モード組み合わせて」。ビジターモード「オブジェクトの構造は、」コンテナ要素は、訪問者がコンテナのすべての要素をトラバース文字が含まれているため、多くの場合、イテレータを使用しています。リストを使用してオブジェクト構造[実施例1]それはイテレータオブジェクトItemtorリスト()メソッドを介して取得し、実装されています。重合のオブジェクトクラス構造は、イテレータを提供しない場合は、カスタム反復モードかもしれません。

「(2)ビジター(訪問者)モード複合モードの組み合わせで」。ビジター(訪問者)モード「標的要素」ので、オブジェクト要素を含むコンテナオブジェクトである場合、使用する必要があり、リーフオブジェクトまたはコンテナ・オブジェクトとすることができる結合モード、図4に示す構造を。
 

                 図ビジターパターン構成は、パターンの組み合わせを含みます

 

 

 

 

 

公開された136元の記事 ウォンの賞賛6 ビュー1538

おすすめ

転載: blog.csdn.net/weixin_42073629/article/details/104437896