一、访问者模式的定义
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.(封装一些作用于某种数据结果中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。)
二、访问者模式的应用
-
访问者模式模式的优点
符合单一职责原则。Element
抽象类的两个子类负责数据的加载,而Visitor
类则负 责报表的展现,两个不同的职责非常明确地分离开来,各自演绎变化;
优秀的扩展性。由于职责分开,继续增加对数据的操作是非常快捷的;
灵活性非常高
-
访问者模式的缺点
具体元素对访问者公布细节;具体元素变更比较困难;访问者依赖的是具体元素,而不是抽象元素,违背了依赖倒置原则。 -
访问者模式的使用场景。
一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作,也就说是用迭代器模式已经不能胜任的场景。需要对一个对象结构中的对象进行很多不同并且不相关的操作,而你想避免让这些操作”污染”这些对象的类
三、访问者模式的实现
abstract class Element {
public abstract void accept(IVisitor visitor);
public abstract void doSomething();
}
class ConcreteElement1 extends Element {
public void doSomething(){
System.out.println("这是元素1");
}
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
class ConcreteElement2 extends Element {
public void doSomething(){
System.out.println("这是元素2");
}
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
interface IVisitor {
public void visit(ConcreteElement1 el1);
public void visit(ConcreteElement2 el2);
}
class ObjectStruture {
public static List<Element> getList(){
List<Element> list = new ArrayList<Element>();
Random 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(Element e: list){
e.accept(new Visitor());
}
}
}
四、访问者模式源码中的应用
在Android源码中的UnifiedEmail项目中的HtmlDocument就使用了访问者模式,Email中的内容可以是Html文档,而Html文档需要解析保存,HtmlDocument就是html节点的一个容器