6月更文挑战|设计模式 —— 访问者模式

340 阅读3分钟

这是我参与更文挑战的第16天,活动详情查看:更文挑战

访问者模式

访问者模式是将数据操作和数据结构分离的模式。访问者基本思想是,系统拥有许多对象构成的比较稳定的对象结构,这些对象拥有一个方法可以来接受访问者对象的访问。访问者是一个接口,拥有一个方法来对访问到的对象结构中不同类型元素做出不同处理。

访问者模式定义:封装作用于某些数据结构中的元素操作,它可以在不改变数据结构的前提下定义作用于这些元素的操作。

实战

访问者模式主要是Visitor(抽象类或接口),它定义了对于元素访问行为,参数就是可访问的元素对象。理论上说访问者对于元素的类型是稳定存在的,若经常增删元素类则使用访问者模式就变得不太适用了。Staff是元素抽象类,被访问对象元素都继承于Staff。Visitor接口实现多个访问Staff的子类对象。CEO和CTO分别是Visitor接口具体实现类,同时都可访问Staff子类对象,不同点在于访问对象的操作有所不同。CEO访问Engineer只关心他的薪资,CTO访问Engineer只关心他的开发信息情况。这也就是访问者模式区别点,对于操作执行上存在差异而这种差异由对象类做区分,可以理解为有所对于if-else形式的替换。

public abstract class Staff{
    public String name;
    public int salary;
    public abstract accept(Visitor visitor);
}

public interface Visitor{
    public void visitor(Engineer engineer);
    public void visitor(Manager manager);
}

public class Engineer extends Staff{

    @override
    public accept(Visitor visitor){
        visitor.visitor(this);
    }
    
    public String getDevelopInfo(){
    
    }
    
}

public class Manager extends Staff{

    @override
    public accept(Visitor visitor){
        visitor.visitor(this);
    }
    
    public int getSalary(){
        return salary;
    }
    
    public int getReport(){
    
    } 
}

public class CEO extends Visitor{
    @override
    public visitor(Engineer engineer){
       engineer.getSalary();
       ....
    }
    
    @override
    public visitor(Manager manager){
       manager.getReport();
       ....
    }
}

public class CTO extends Visitor{
    @override
    public visitor(Engineer engineer){
       engineer.getDevelopInfo();
       ....
    }
    
    @override
    public visitor(Manager manager){
       manager.getSalary();
       ....
    }
}

注解形式

在Android开发中注解也是经常接触的形式。注解分为两种类型:运行时注解,编译期间注解。编译注解核心依赖APT,当我们通过APT处理注解时,最终会将获取到的元素转换为相应的Element元素,以便获取到它们对应信息。

//元素基类
public interface Element extends javax.lang.model.AnnotatedConstruct {
 
  ElementKind getKind();//获取元素类型
   ///... 
  <R, P> R accept(ElementVisitor<R, P> v, P p);//接受访问者的访问
}
//访问者ElementVisitor
public interface ElementVisitor<R, P> {
 
  R visit(Element e, P p);

  R visit(Element e);
  
  R visitPackage(PackageElement e, P p);

  R visitType(TypeElement e, P p);
 
  R visitVariable(VariableElement e, P p);
 
  R visitExecutable(ExecutableElement e, P p);

  R visitTypeParameter(TypeParameterElement e, P p);

  R visitUnknown(Element e, P p);
}

总结

访问者模式大多数情况下不太会接触过,但是但真正用到时还是非常需要它的。在考虑使用设计模式前需要思考对象结构是否足够稳定,使用访问者模式是否能够优化我们的代码,而不是使我们的代码变得更复杂。

参考

  • 《Android源码设计模式》