1. 程式人生 > 實用技巧 >java23種設計模式-行為型模式-訪問者模式

java23種設計模式-行為型模式-訪問者模式

一、定義

訪問者(Visitor)模式的定義:將作用於某種資料結構中的各元素的操作分離出來封裝成獨立的類,使其在不改變資料結構的前提下可以新增作用於這些元素的新的操作,為資料結構中的每個元素提供多種訪問方式。它將對資料的操作與資料結構進行分離,是行為類模式中最複雜的一種模式。

二、優點及缺點

優點:

1、擴充套件性好。能夠在不修改物件結構中的元素的情況下,為物件結構中的元素新增新的功能。

2、複用性好。可以通過訪問者來定義整個物件結構通用的功能,從而提高系統的複用程度。

3、靈活性好。訪問者模式將資料結構與作用於結構上的操作解耦,使得操作集合可相對自由地演化而不影響系統的資料結構。

4、符合單一職責原則。訪問者模式把相關的行為封裝在一起,構成一個訪問者,使每一個訪問者的功能都比較單一。

缺點:

1、增加新的元素類很困難。在訪問者模式中,每增加一個新的元素類,都要在每一個具體訪問者類中增加相應的具體操作,這違背了“開閉原則”。

2、破壞封裝。訪問者模式中具體元素對訪問者公佈細節,這破壞了物件的封裝性。

3、違反了依賴倒置原則。訪問者模式依賴了具體類,而沒有依賴抽象類。

三、程式碼實現:

訪問者類介面:

package com.example.demo.sjms.fangwenzhemoshi;

/**
 *  @Author: caesar
 *  @Date:2020年12月22日 17:12:35
 *  @Description: 訪問者類介面
 */
public interface
Visitor { /** * @Author: caesar * @Date:2020年12月22日 17:12:33 * @Description: 訪問方法 */ public void visitor(ConcreteElementA concreteElementA); public void visitor(ConcreteElementB concreteElementB); }

具體訪問者A:

package com.example.demo.sjms.fangwenzhemoshi;

/**
 *  @Author: caesar
 *  @Date:2020年12月22日 17:12:31
 *  @Description: 具體訪問者A
 
*/ public class ConcreteVisitorA implements Visitor{ @Override public void visitor(ConcreteElementA concreteElementA) { System.out.println("訪問者A訪問"); concreteElementA.operationA(); } @Override public void visitor(ConcreteElementB concreteElementB) { System.out.println("訪問者A訪問"); concreteElementB.operationB(); } }

具體訪問者B:

package com.example.demo.sjms.fangwenzhemoshi;

/**
 *  @Author: caesar
 *  @Date:2020年12月22日 17:12:59
 *  @Description: 抽象訪問者B
 */
public class ConcreteVisitorB implements Visitor{
    @Override
    public void visitor(ConcreteElementA concreteElementA) {
        System.out.println("訪問者B訪問");
        concreteElementA.operationA();
    }

    @Override
    public void visitor(ConcreteElementB concreteElementB) {
        System.out.println("訪問者B訪問");
        concreteElementB.operationB();
    }
}

抽象元素類:

package com.example.demo.sjms.fangwenzhemoshi;

/**
 *  @Author: caesar
 *  @Date:2020年12月22日 17:12:21
 *  @Description: 抽象元素類
 */
public interface Element {
    /**
     *  @Author: caesar
     *  @Date:2020年12月22日 17:12:55
     *  @Description: 接收訪問者
     */
    public void accept(Visitor visitor);
}

具體元素類A:

package com.example.demo.sjms.fangwenzhemoshi;

/**
 *  @Author: caesar
 *  @Date:2020年12月22日 17:12:57
 *  @Description: 具體物件類A
 */
public class ConcreteElementA implements Element{

    /**
     *  @Author: caesar
     *  @Date:2020年12月22日 17:12:55
     *  @Description: 接收訪問者
     */
    @Override
    public void accept(Visitor visitor) {
        visitor.visitor(this);
    }
    public void operationA(){
        System.out.println("這是A的具體操作。。。。。。");
    }
}

具體元素類B:

package com.example.demo.sjms.fangwenzhemoshi;

/**
 *  @Author: caesar
 *  @Date:2020年12月22日 17:12:57
 *  @Description: 具體物件類B
 */
public class ConcreteElementB implements Element{
    /**
     *  @Author: caesar
     *  @Date:2020年12月22日 17:12:55
     *  @Description: 接收訪問者
     */
    @Override
    public void accept(Visitor visitor) {
        visitor.visitor(this);
    }
    public void operationB(){
        System.out.println("這是B的具體操作。。。。。。");
    }

}

物件結構類:

package com.example.demo.sjms.fangwenzhemoshi;

import java.util.ArrayList;
import java.util.List;

/**
 *  @Author: caesar
 *  @Date:2020年12月22日 17:12:09
 *  @Description: 結構物件
 */
public class ObjectStructure {
    private List<Element> list;
    public ObjectStructure(){
        list = new ArrayList<Element>();
    }
    // 新增
    public void add(Element element){
        list.add(element);
    }
    // 刪除
    public void remove(Element element){
        list.remove(element);
    }
    // 接收訪問者
    public void accept(Visitor visitor){
        list.forEach(element -> {
            element.accept(visitor);
        });
    }
}

測試類:

package com.example.demo.sjms.fangwenzhemoshi;

/**
 *  @Author: caesar
 *  @Date:2020年12月22日 17:12:54
 *  @Description: 測試類
 */
public class Test {
    public static void main(String[] args) {
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.add(new ConcreteElementA());
        objectStructure.add(new ConcreteElementB());
        objectStructure.accept(new ConcreteVisitorA());
        objectStructure.accept(new ConcreteVisitorB());
    }
}

四、原始碼級別

五、總結

主要解決:物件結構相對穩定,但其操作演算法經常變化的程式。物件結構中的物件需要提供多種不同且不相關的操作,而且要避免讓這些操作的變化影響物件的結構。物件結構包含很多型別的物件,希望對這些物件實施一些依賴於其具體型別的操作。