访问者模式一

2022-10-25 18:34:32 浏览数 (2)

代码语言:javascript复制
public abstract class Employee {  
    // 抽象的员工类,有自己的一些属性
    private String name;  
    private int salary;
    
    // getter/setter

    // 提供一个方法,输出员工信息
    public final void report(){
        String info = "姓名:"  name "t薪水:" salary "t"; 
        info = info   this.getOtherInfo(); // 一个钩子,子类提供他自己的信息
        System.out.println(info);
    }

    //子类去实现自己独有的信息
    protected abstract String getOtherInfo();
}

// 普通员工
public class CommonEmployee extends Employee {
    private String job; 
    // getter/setter

    // 普通员工独特的信息就是提供自己的工作是什么
    protected String getOtherInfo() {
        return "工作:"  job   "t";
    }
}

// 经理
public class Manager extends Employee { 
    private String performance;  
    
    // 经理提供的信息就是业绩
    protected String getOtherInfo(){
        return "业绩:"  this.performance   "t";
    }
}

这个问题是外部场景只能调用 report 输出信息,能输出的信息也都是子类设计时定好的。如同邀请朋友来家参观,参观后,不同的人有不同的描述,这个例子挺好的,用现在的方式不好弄。

所以有了访问者模式,提供一个 Visitor。

代码语言:javascript复制
// 这麻烦的是要为每个子类单独写方法,因为不同子类要 report 的内容是不同的
public interface IVisitor {  
    public void visit(CommonEmployee commonEmployee);
    public void visit(Manager manager);
}

// 将原来 Manager 自己维护的 report 和 getOtherInfo 都放到 Visitor 里
public class Visitor implements IVisitor {  
    public void visit(CommonEmployee commonEmployee) {
        System.out.println(this.getCommonEmployee(commonEmployee));
    }  

    public void visit(Manager manager) {
        System.out.println(this.getManagerInfo(manager));
    }
    
    private String getBasicInfo(Employee employee){  
        return "姓名:"  name "t薪水:" salary "t"; 
    }
    
    private String getManagerInfo(Manager manager){
        String basicInfo = this.getBasicInfo(manager);  
        String otherInfo = "业绩:" manager.getPerformance()   "t"; 
        return basicInfo   otherInfo;
    }
    
    private String getCommonEmployee(CommonEmployee commonEmployee){ 
        String basicInfo = this.getBasicInfo(commonEmployee); 
        String otherInfo = "工作:" commonEmployee.getJob() "t"; 
        return basicInfo   otherInfo;
    }
}
代码语言:javascript复制
public abstract class Employee {  
    // 抽象的员工类,有自己的一些属性
    private String name;  
    private int salary;
    
    // getter/setter

    // 接收一个访问者
    protected abstract void accept(IVisitor visitor);
}

public class CommonEmployee extends Employee { 
    private String job;  
    
    @Override  
    public void accept(IVisitor visitor){
        // 一接收一个访问者就输出了自己的信息描述
        visitor.visit(this);
    }
}

要输出信息,原来调用 Emplyee 的 report,现在调用 accept,参数传进来一个 Visitor。主要的优点就是如果修改输出内容,不需要修改 Employee 这些子类,只需要修改访问者,但是同样在修改类,修改访问者也没觉得比修改被访问者高级。

应该说在一个项目中,Employee 肯定在许多地方都使用到,对于它的修改可能牵一发而动全身。而 Visitor 是专门创造出来为 Employee 服务的,所以修改它不会有太大的影响。

缺点是两者联系笔记紧密,Visitor 知道 Employee 的细节,如果 Employee 的属性改了,Visitor 也要修改,但是 Visitor 作为专门为 Employee 服务的仆人,倒也符合直觉。

然后职责单一,输出的职责单独一个类去负责。

0 人点赞