访问者模式——java设计模式(二十五)

简介

访问者模式(Visitor Pattern):表示一个用于作用于某对象结构中的各个元素的操作。让用户在不改变各元素的类的前提下定义作用于这些元素的新操作。

  • 为了以不同的方式操作复杂对象结构中的不同类型元素

结构和实现

  • 角色包括:
    • 抽象访问者:为对象结构中的每一个具体元素类声明一个访问操作。
    • 具体访问者:实现对每一具体元素的访问方法。
    • 抽象元素:声明accept方法,接收访问者的访问操作,通常是抽象类和接口。
    • 具体元素:实现accept方法,调用访问者的对应的访问方法。
    • 对象结构:存放元素对象并提供遍历方法,可以使用组合模式实现。
  • 访问者结构。
    180516.visitor.png
  • 访问者模式有两个层次结构:访问者的层次、元素层次。
  • 不同具体元素通过接收不同的具体访问者,以自身为参数,执行访问者中操作不同元素的方法,这称为双重分派机制。
public class ConcreteElementA implements Element  
{  
    public void accept(Visitor visitor)  
    {  
        visitor.visit(this);  
    }  

    public void operationA()  
    {  
        //业务方法  
    }  
}  

实例

  • 开发员工信息管理系统,员工包括正式工和临时工,每周人力资源部和财务部需要对员工数据进行汇总,包括工作时间、工资等。正式员工和临时工的工资和工作时间计算方法不一致。
    180516.employee.png
  • 财务部门的访问方法。
pubic class FADepartment extends Department  
{  
    //实现财务部对全职员工的访问  
    public void visit(FulltimeEmployee employee)  
    {  
        int workTime = employee.getWorkTime();  
        double weekWage = employee.getWeeklyWage();  
        if(workTime > 40)  
        {  
            weekWage = weekWage + (workTime - 40) * 100;  
        }  
        else if(workTime < 40)  
        {  
            weekWage = weekWage - (40 - workTime) * 80;  
            if(weekWage < 0)  
            {  
                weekWage = 0;  
            }  
        }  
        System.out.println("正式员工" + employee.getName() + "实际工资为:" + weekWage + "元。");             
    }  

    //实现财务部对兼职员工的访问  
    public void visit(ParttimeEmployee employee)  
    {  
        int workTime = employee.getWorkTime();  
        double hourWage = employee.getHourWage();  
        System.out.println("临时工" + employee.getName() + "实际工资为:" + workTime * hourWage + "元。");       
    }         
}  
  • HR部门的访问方法。
public class HRDepartment extends Department  
{  
    //实现人力资源部对全职员工的访问  
    public void visit(FulltimeEmployee employee)  
    {  
        int workTime = employee.getWorkTime();  
        System.out.println("正式员工" + employee.getName() + "实际工作时间为:" + workTime + "小时。");  
        if(workTime > 40)  
        {  
            System.out.println("正式员工" + employee.getName() + "加班时间为:" + (workTime - 40) + "小时。");  
        }  
        else if(workTime < 40)  
        {  
            System.out.println("正式员工" + employee.getName() + "请假时间为:" + (40 - workTime) + "小时。");  
        }                         
    }  

    //实现人力资源部对兼职员工的访问  
    public void visit(ParttimeEmployee employee)  
    {  
        int workTime = employee.getWorkTime();  
        System.out.println("临时工" + employee.getName() + "实际工作时间为:" + workTime + "小时。");  
    }         
}  

联用组合模式

  • 元素可以使用组合模式表示树形结构。
    180516.composite.png

优缺点和适用范围

  • 优点:
    • 增加新的访问操作容易。只需要增加一个新的访问者类,无需修改源码,符合开闭原则。
    • 访问操作集中。访问操作集中在访问者中,而不是分散在元素中,类的职责清晰,有利于元素对象的复用。
  • 缺点:
    • 增加新的元素很难。需要在新的抽象访问者中增加一个新的操作,并在每一具体访问者中增加,违背开闭原则,且修改麻烦。
    • 破坏封装性。访问者对象访问并且调用每一个元素对象的操作,对象又是必须暴露自己的内部状态和操作。
  • 适用环境:
    • 对象结构中包含多个类型的对象,希望针对不同类型提供不同的操作。
    • 不希望在对象中增加访问操作,需要对象本身和访问操作分离。
    • 元素对象的类型很少改变,但是需要经常增加新的操作。

jdk中的应用

  • 提供对访问者模式的支持,javax.lang.model.element.Element和javax.lang.model.element.ElementVisitor分别对应抽象元素和抽象访问者。
    180518.ElementVisitor.png

猜你喜欢

转载自blog.csdn.net/qq_40369829/article/details/80374079