Java设计模式--访问者模式

访问者模式【Visitor Pattern 】

以打印公司员工的信息报表为例。下面先看下类图。

这里写图片描述

使用了一个模版方法模式,把所要的信息都打印出来。这样子写出来的代码就不太符合公司不同管理层的需要,不能满足各自的需求。

每个普通员工类和经理类都一个方法 report,那是否可以把这个方法提取到另外一个类中来实现呢。最初的类图如下:

这里写图片描述

两个类中都有report()方法,那么再进行一些改善。

这里写图片描述

这样子就将report()方法提炼出来了,再看下下面这个。

这里写图片描述

在抽象类 Employee 中增加了 accept 方法,这个方法是定义我这个类可以允许被谁来访问,也就定义一类访问者,在具体的实现类中调用访问者的方法。

那在具体类中就可以设置访问者了。

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

在主类进行调用时直接传入访问者进行访问公司不同角色的信息。

for(Employee emp:mockEmployee()){
    emp.accept(new Visitor());
}

再看一下他的通用类图:

这里写图片描述

来看一下这几个角色的职责:
抽象访问者(Visitor) :抽象类或者接口,声明访问者可以访问哪些元素,具体到程序中就是 visit方法的参数定义哪些对象是可以被访问的;

具体访问者(ConcreteVisitor):访问者访问到一个类后该怎么干(哎,这个别读歪了),要做什么事情;

抽象元素(Element) :接口或者抽象类,声明接受那一类型的访问者访问,程序上是通过 accept 方法中的参数来定义;

具体元素: (ConcreteElement):实现 accept 方法,通常是 visitor.visit(this),基本上都形成了一个套路了;

结构对象(ObjectStruture):容纳多个不同类、不同接口的容器,比如 List、Set、Map 等,在项目中,一般很少抽象出来这个角色;

总结:
应用场景:
先与迭代器模式比较一下,迭代器模式只能访问同类或同接口的数据, (当然了,你使用 instanceof 的话,能访问所有的数据,这个不争论) ,而访问者模式是对迭代器模式的扩充,可以遍历不同的对象,然后执行不同的操作,也就是针对访问的对象不同,执行不同的操作。故可以将访问者模式应用到遍历不同的对象,然后执行不同的操作的项目当中。比如统计(统计公司人员的工资等)、有多个访问者的情况(上述的访问者其实可以再进行细分,一个用于展示报表的信息,一个用于计算报表中的一些信息)、充当拦截器(以后进行补充)。

优点
(1)符合单一职责原则,具体元素角色也就是Employee 这个类的两个子类负责数据的加载,而Visitor 类则负责报表的展现,两个不同的职责非常明确的分离开来,各自演绎而变化。

(2)由于职责分开,继续增加对数据的操作是非常快捷的。扩展性良好。

缺点:
(1)访问者要访问一个类就必然要求这个类公布一些方法,也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的;

(2)具体角色的增加删除修改都是比较苦难的,就上面那个例子,你想想,你要是想增加一个成员变量,比如年龄 age,Visitor 就需要修改,如果 Visitor 是一个还好说,多个呢?业务逻辑再复杂点呢。

发布了46 篇原创文章 · 获赞 3 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章