設計模式學習筆記——訪問者模式

訪問者模式

訪問者模式,封裝某些作用於某種數據結構中各元素的操作,它可以在不改變數據結構的前提下定義作用於這些元素的新的操作。(行爲類模式)

結構圖


抽象訪問者Visitor:抽象類或者接口,聲明訪問者可以訪問哪些元素,具體到程序中就是visit方法中的參數定義哪些對象是可以被訪問的。

訪問者ConcreteVisitor:實現抽象訪問者所聲明的方法,它影響到訪問者訪問到一個類後該幹什麼,要做什麼事情。

抽象元素類Element:接口或者抽象類,聲明接受哪一個類訪問者訪問,程序上是通過accept方法中的參數來定義的。抽象方法分爲:本身的業務邏輯和允許接受哪類訪問者來訪問。

元素類:實現抽象元素類所聲明的accept方法,通常都是visitor.visit(this)。

結構對象ObjectStruture:一個元素的容器,一般包含一個容納多個不同類、不同接口的容器。

demo

一個簡單的例子:
public class A {

	public void method1(){
		System.out.println("I am A");
	}
	
	public void method2(B b){
		b.show(this);
	}
	
}

public class B {

	public void show(A a){
		a.method1();
	}
	
}

public class Test {

	public static void main(String[] args) {
		A a = new A();
		a.method1();
		
		a.method2(new B());
	}
	
}
這裏是兩種打印方式,method1只A之間打印,method2是通過B來調用A的打印方法。這裏B就是一個簡單的訪問者。

代碼實現

抽象被訪問者Element:
/**
 * 抽象元素類,被訪問者
 *
 * @author xukai 2016年4月30日 下午10:42:18
 * 
 */
public abstract class Element {

	/**
	 * 接受訪問
	 * @param visitor
	 */
	public abstract void accept(IVisitor visitor);

	public abstract void doSomething();
	
}
具體被訪問者ConcreteElement:
/**
 * 具體元素類,被訪問者
 *
 * @author xukai 2016年4月30日 下午10:46:09
 * 
 */
public class ConcreteElement1 extends Element {

	@Override
	public void accept(IVisitor visitor) {
		visitor.visit(this);
	}

	@Override
	public void doSomething() {
		System.out.println("元素1");
	}

}

/**
 * 具體元素類,被訪問者
 *
 * @author xukai 2016年4月30日 下午10:46:30
 * 
 */
public class ConcreteElement2 extends Element {

	@Override
	public void accept(IVisitor visitor) {
		visitor.visit(this);
	}

	@Override
	public void doSomething() {
		System.out.println("元素2");
	}

}

抽象訪問者IVisitor:
/**
 * 抽象訪問者
 *
 * @author xukai 2016年4月30日 下午10:46:00
 * 
 */
public interface IVisitor {

	/**
	 * 訪問元素1
	 * @param ele
	 */
	public void visit(ConcreteElement1 ele);
	
	/**
	 * 訪問元素2
	 * @param ele
	 */
	public void visit(ConcreteElement2 ele);
	
}
具體訪問者Visitor:
/**
 * 具體訪問者,可以訪問某個元素
 *
 * @author xukai 2016年4月30日 下午10:46:34
 * 
 */
public class Visitor implements IVisitor {

	@Override
	public void visit(ConcreteElement1 ele) {
		ele.doSomething();
	}

	@Override
	public void visit(ConcreteElement2 ele) {
		ele.doSomething();
	}

}

結構對象ObjectStruture:
package com.xk.day0430.visitor.demo;

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

/**
 * 容器,裝元素,即被訪問者
 *
 * @author xukai 2016年4月30日 下午10:47:08
 * 
 */
public class ObjectStruture {

	public static List getList() {
		List list = new ArrayList();
		Random random = new Random();
		for (int i = 0; i < 10; i++) {
			int a = random.nextInt(100);
			if (a > 50) {
				list.add(new ConcreteElement1());
			} else {
				list.add(new ConcreteElement2());
			}
		}
		return list;
	}

}

客戶端:
import java.util.List;

public class Client {

	public static void main(String[] args) {
		List<Element> list = ObjectStruture.getList();
		for (Element e : list) {
			e.accept(new Visitor());
		}
	}

}

總結

優點

符合單一職責原則:適用訪問者模式時,元素類中需要封裝在訪問者中的操作必定是與元素類本身關係不大且是易變的操作,使訪問者模式一方面符合單一職責原則,另一方面,被封裝的操作通常是易變的,所以發生變化時,可以在不改變元素類本身的前提下,實現變化部分擴展。
擴展性好:元素可以通過接受不同的訪問者來實現對不同操作的擴展。

缺點

當增加性的元素類比較困難。通過代碼可以看到,在訪問者類中,每一個元素類都有它對應的處理方法,即每增加一個元素類都需要修改訪問者類(包括子類或實現類),修改起來相當麻煩。再元素類數據不確定的情況下,慎用訪問者模式。如果一個項目基本功能確定了,元素類數據基本確定不變了,變得只是元素類內的操作,這個時候可以使用訪問者模式對原來的代碼進行重構一遍。


發佈了94 篇原創文章 · 獲贊 66 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章