访问者模式
2018-04-17 本文已影响7人
begonia_rich
Java的设计模式很多,以前看过很多遍,最近才搞懂了访问者模式,真是惭愧,看了一些github的源码有一些访问者模式的例子,由此写一个demo加深印象,共勉
提要
访问者模式最核心的点:分离数据和行为
注意它与模版方法模式的区别,一个是提到父类完成模版,另一个是将整个方法委托出去,灵活性更大,同时复杂度升高。
结构
主要有访问者(Visitor),被访问对象(Element)两个角色,被访问对象的行为被抽到了访问者中进行。
代码示例
抽象接口定义
/**
* 访问者
* @author xiezhengchao
* @since 2018/4/17 18:16
*/
public interface Visitor{
/**
* 访问元素具体操作
*/
void visit(ElementA elementA);
void visit(ElementB elementB);
/**
* 抽象行为的入口
*/
void go(Element element);
}
/**
* 行为抽象,一般这个接口都是已有的
*
* @author xiezhengchao
* @since 2018/4/17 18:33
*/
public interface GoAble{
/**
* do it
*/
void go();
}
/**
* 待访问元素
* @author xiezhengchao
* @since 2018/4/17 18:17
*/
public interface Element extends GoAble{
/**
* 回调访问者,让访问者决定具体执行子对象的行为
*/
void accept(Visitor visitor);
}
下面看具体实现
/**
* 访问者实现
*/
public class DefaultVisitor implements Visitor{
/**
* 行为入口,由element触发
*/
@Override
public void go(Element element){
// 直接去accept触发visit到我们自己的行为实现
element.accept(this);
}
/**
* 从不同的元素中获取信息 name()
*/
@Override
public void visit(ElementA elementA){
print(elementA.name());
}
/**
* 从不同的元素中获取信息 surname()
*/
@Override
public void visit(ElementB elementB){
print(elementB.surname());
}
/**
* 比如这是统一的处理方法流程
*/
private void print(String str){
System.out.println(str);
}
}
/**
* 让所有元素都有相同的行为,和模版方法是彻底不同的思路实现,这个模式明显更犀利
*
* @author xiezhengchao
* @since 2018/4/17 18:32
*/
public abstract class AbstractElement implements Element{
private Visitor visitor;
public AbstractElement(Visitor visitor){
this.visitor = visitor;
}
@Override
public void go(){
// 将抽象出去的行为 委托给访问者完成
visitor.go(this);
}
}
public class ElementA extends AbstractElement{
public ElementA(Visitor visitor){
super(visitor);
}
@Override
public void accept(Visitor visitor){
visitor.visit(this);
}
public String name(){
return "I am A";
}
}
public class ElementB extends AbstractElement{
public ElementB(Visitor visitor){
super(visitor);
}
@Override
public void accept(Visitor visitor){
visitor.visit(this);
}
public String surname(){
return "I am sur B";
}
}
接下来使用,使用起来简单明了
/**
* 访问者模式
* 1分离数据和行为
* 2存在着相似的操作,避免重复代码
*
* @author xiezhengchao
* @since 2018/4/17 18:20
*/
public class Client{
public static void main(String[] args){
Visitor visitor = new DefaultVisitor();
// 通过访问者模式将数据和行为剥离,这看起来相当的明显,虽然还是调用的Element的方法,但是实际上方法是在访问者中进行,数据在元素中存储
new ElementA(visitor).go();
new ElementB(visitor).go();
}
}
注释里已经把核心的功能描述的相当清楚了,这里不再赘述
总结
设计模式多种多样,平常用的多的也就那些,不怎么用,但是优秀的设计模式也值得多去回味思考。