当前位置: 首页 > 编程笔记 >

Java使用访问者模式解决公司层级结构图问题详解

华子航
2023-03-14
本文向大家介绍Java使用访问者模式解决公司层级结构图问题详解,包括了Java使用访问者模式解决公司层级结构图问题详解的使用技巧和注意事项,需要的朋友参考一下

本文实例讲述了Java使用访问者模式解决公司层级结构图问题。分享给大家供大家参考,具体如下:

一. 模式定义

访问者模式:是表示一个作用于某对象结构中各个元素的操作,它使用户可以在不改变各元素类的前提下定义作用于这些元素的新操作。

二. 模式举例

1 模式分析

我们借用公司层级结构来说明这一模式。

2 访问者模式静态类图

3 代码示例

3.1 抽象员工一Staff

package com.demo.structure;
import com.demo.visitor.IVisitor;
/**
 * 抽象员工类
 *
 * @author
 *
 */
public abstract class Staff {
  // 员工号
  protected String no;
  // 职工名字
  protected String name;
  // 职位
  protected String position;
  // 薪资
  protected float salary;
  // 私有属性 长度字符串
  private int length;
  // 构造方法
  public Staff(String no, String name, String position, float salary) {
    this.no = no;
    this.name = name;
    this.position = position;
    this.salary = salary;
    // 计算总字节长度
    this.length += (no == null || "".equals(no.trim())) ? 0
        : no.getBytes().length;
    this.length += (name == null || "".equals(name.trim())) ? 0 : name
        .getBytes().length;
    this.length += (position == null || "".equals(position.trim())) ? 0
        : position.getBytes().length;
    this.length += String.valueOf(salary).getBytes().length;
  }
  // 获得用户基本信息
  public void printUserBaseInfo() {
    System.out.println("-|" + this.no + " " + this.name + " "
        + this.position + " " + this.salary);
  }
  // 添加员工信息
  public abstract void add(Staff staff);
  // 删除员工
  public abstract Staff remove(String no);
  // 接收访问者对象
  public abstract void accept(IVisitor visitor);
  public String getNo() {
    return no;
  }
  public void setNo(String no) {
    this.no = no;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getPosition() {
    return position;
  }
  public void setPosition(String position) {
    this.position = position;
  }
  public float getSalary() {
    return salary;
  }
  public void setSalary(float salary) {
    this.salary = salary;
  }
}

3.2 管理者一Manager

package com.demo.structure;
import java.util.ArrayList;
import com.demo.visitor.IVisitor;
/**
 * 管理人员(手下有其他员工的人)
 *
 * @author
 *
 */
public class Manager extends Staff {
  // 存储手下员工信息
  private final ArrayList<Staff> arrayList = new ArrayList<Staff>();
  // 构造方法
  public Manager(String no, String name, String position, float salary) {
    super(no, name, position, salary);
  }
  /**
   * 增加一个员工
   */
  @Override
  public void add(Staff staff) {
    this.arrayList.add(staff);
  }
  /**
   * 删除员工信息
   */
  @Override
  public Staff remove(String no) {
    Staff staff = null;
    if (no != null && !"".equals(no.trim())) {
      for (int i = 0; i < this.arrayList.size(); i++) {
        if (this.arrayList.get(i) == null) {
          continue;
        }
        if (no.equals(this.arrayList.get(i).getNo())) {
          staff = this.arrayList.remove(i);
          break;
        }
      }
    }
    return staff;
  }
  // 接收访问者对象
  @Override
  public void accept(IVisitor visitor) {
    // 访问自身
    visitor.visit(this);
    // 遍历list列表中的各个元素对象,接收访问者对象
    for (int i = 0; i < this.arrayList.size(); i++) {
      if (this.arrayList.get(i) == null) {
        continue;
      }
      // 接收访问者对象
      this.arrayList.get(i).accept(visitor);
    }
  }
}

3.3 普通员工一Employees

package com.demo.structure;
import com.demo.visitor.IVisitor;
/**
 * 普通员工(真正干活的人)
 *
 * @author
 *
 */
public class Employees extends Staff
{
  // 构造方法
  public Employees(String no, String name, String position, float salary)
  {
    super(no, name, position, salary);
  }
  /**
   * 添加员工信息
   */
  @Override
  public void add(Staff staff)
  {
    return;
  }
  /**
   * 删除员工信息
   */
  @Override
  public Staff remove(String no)
  {
    // 直接返回null
    return null;
  }
  // 接收访问者对象
  public void accept(IVisitor visitor)
  {
    visitor.visit(this);
  }
}

3.4 访问者接口一IVisitor

package com.demo.visitor;
import com.demo.structure.Employees;
import com.demo.structure.Manager;
/**
 * 访问者接口
 *
 * @author
 *
 */
public interface IVisitor {
  // 访问管理者
  public void visit(Manager manager);
  // 访问普通员工
  public void visit(Employees employees);
}

3.5 员工基本信息访问者一PrintBaseInfoVistor

package com.demo.visitor;
import com.demo.structure.Employees;
import com.demo.structure.Manager;
/**
 * 打印基本信息访问者
 *
 * @author
 *
 */
public class PrintBaseInfoVisitor implements IVisitor {
  /**
   * 访问管理者对象
   */
  public void visit(Manager manager) {
    System.out.print("- 管理者:");
    manager.printUserBaseInfo();
  }
  /**
   * 访问普通员工对象
   */
  public void visit(Employees employees) {
    System.out.print("- 一般员工:");
    employees.printUserBaseInfo();
  }
}

3.6 创建统计员工薪资的访问者接口一ISalaryVistor

package com.demo.visitor;
/**
 * 计算薪资访问者
 *
 * @author
 *
 */
public interface ISalaryVisitor extends IVisitor {
  // 统计管理者薪资情况
  public void printManagerTotalSalary();
  // 统计一般员工薪资情况
  public void printEmployeesTotalSalary();
  // 统计所有员工薪资情况
  public void printTotalSalary();
}

3.7 统计员工薪资访问者实现一SalaryVistor

package com.demo.visitor;
import com.demo.structure.Employees;
import com.demo.structure.Manager;
/**
 * 计算薪资访问者具体实现
 *
 * @author
 *
 */
public class SalaryVisitor implements ISalaryVisitor {
  // 管理者薪资总和
  private float managerSalary;
  // 普通员工薪资总和
  private float employeesSalary;
  public SalaryVisitor() {
    managerSalary = 0;
    employeesSalary = 0;
  }
  // 访问管理者
  public void visit(Manager manager) {
    managerSalary += manager.getSalary();
  }
  // 访问普通员工
  public void visit(Employees employees) {
    employeesSalary += employees.getSalary();
  }
  // 统计一般员工薪资情况
  public void printEmployeesTotalSalary() {
    System.out.println("一般员工薪资总和:" + employeesSalary);
  }
  // 统计管理者薪资情况
  public void printManagerTotalSalary() {
    System.out.println("管理者薪资总和:" + managerSalary);
  }
  // 统计所有员工薪资情况
  public void printTotalSalary() {
    System.out.println("员工薪资总和:" + (managerSalary + employeesSalary));
  }
}

3.8 客户端测试一Client

package com.demo;
import com.demo.structure.Employees;
import com.demo.structure.Manager;
import com.demo.structure.Staff;
import com.demo.visitor.PrintBaseInfoVisitor;
import com.demo.visitor.SalaryVisitor;
/**
 * 主应用程序
 *
 * @author
 *
 */
public class Client {
  /**
   * @param args
   */
  public static void main(String[] args) {
    // 公司CEO
    Staff boss = new Manager("1", "大老板", "CEO", 100000);
    /**
     * CEO手下有若干部门经理
     */
    // 财务部经理
    Staff financeManager = new Manager("11", "张总", "财务部经理", 60000);
    // 人事部经理
    Staff personnelManager = new Manager("12", "王总", "人事部经理", 60000);
    // 技术部经理
    Staff technicalManager = new Manager("13", "陈总", "技术部经理", 60000);
    /**
     * 技术部门还有助理和若干主管
     */
    // 技术部门助理
    Staff deptAssistant = new Manager("1301", "王助理", "部门助理", 20000);
    // 技术部门主管1
    Staff deptManager1 = new Manager("1302", "主管1", "技术主管", 30000);
    /**
     * 技术主管deptManager1 下面还有软件工程师(最终干活的人)
     */
    Staff softwareEngineer1 = new Employees("1302001", "张三", "软件工程师", 5000);
    Staff softwareEngineer2 = new Employees("1302002", "李四", "软件工程师", 5500);
    Staff softwareEngineer3 = new Employees("1302003", "王五", "软件工程师", 4500);
    // 为技术主管1添加员工信息
    deptManager1.add(softwareEngineer1);
    deptManager1.add(softwareEngineer2);
    deptManager1.add(softwareEngineer3);
    // 技术部门主管2
    Staff deptManager2 = new Manager("1303", "主管2", "技术主管", 30000);
    // 为技术部经理 添加:部门助理、技术主管1和技术主管2
    technicalManager.add(deptAssistant);
    technicalManager.add(deptManager1);
    technicalManager.add(deptManager2);
    // 市场部经理
    Staff marketingManager = new Manager("14", "吴总", "市场部经理", 60000);
    // 为CEO 添加:财务部经理、人事部经理、技术部经理和市场部经理
    boss.add(financeManager);
    boss.add(personnelManager);
    boss.add(technicalManager);
    boss.add(marketingManager);
    // 打印CEO 信息
    // boss.printUserBaseInfo();
    // 打印CEO 手下员工信息
    boss.accept(new PrintBaseInfoVisitor());
    /**
     * 统计员工薪资情况
     */
    // 创建统计员工薪资访问者
    SalaryVisitor visitor = new SalaryVisitor();
    // 让大老板接受该访问者
    boss.accept(visitor);
    // 管理者薪资统计情况
    visitor.printManagerTotalSalary();
    // 一般员工薪资统计情况
    visitor.printEmployeesTotalSalary();
    // 所有员工薪资统计情况
    visitor.printTotalSalary();
  }
}

4 运行结果

- 管理者:-|1 大老板 CEO 100000.0
- 管理者:-|11 张总 财务部经理 60000.0
- 管理者:-|12 王总 人事部经理 60000.0
- 管理者:-|13 陈总 技术部经理 60000.0
- 管理者:-|1301 王助理 部门助理 20000.0
- 管理者:-|1302 主管1 技术主管 30000.0
- 一般员工:-|1302001 张三 软件工程师 5000.0
- 一般员工:-|1302002 李四 软件工程师 5500.0
- 一般员工:-|1302003 王五 软件工程师 4500.0
- 管理者:-|1303 主管2 技术主管 30000.0
- 管理者:-|14 吴总 市场部经理 60000.0
管理者薪资总和:420000.0
一般员工薪资总和:15000.0
员工薪资总和:435000.0

三. 该模式设计原则

1 "开-闭"原则

2 单一职责原则

四. 使用场合

1 如果在一个对象结构中包含很多不同类型的对象,它们有不同的接口,而想对这些不同对象实施一些依赖于具体类的操作。

2 需要对一个对象结构中的对象进行很多不同的并且不相关操作,而想避免让这些操作与这些对象的类关联起来。访问者模式使得可以将相关操作集中起来,单独定义在一个类中。

3 当该对象结构被很多应用共享时,用访问者模式让每个应用仅包含需要用到的操作。

4 定义对象结构的类很少改变,但经常需要在此结构中定义新的操作。

五. 访问者模式静态类图

更多java相关内容感兴趣的读者可查看本站专题:《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》

希望本文所述对大家java程序设计有所帮助。

 类似资料:
  • 本文向大家介绍JAVA设计模式之访问者模式详解,包括了JAVA设计模式之访问者模式详解的使用技巧和注意事项,需要的朋友参考一下 在阎宏博士的《JAVA与模式》一书中开头是这样描述访问者(Visitor)模式的:   访问者模式是对象的行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。 分派的概念   变量被声明时的

  • 本文向大家介绍JAVA设计模式之访问者模式原理与用法详解,包括了JAVA设计模式之访问者模式原理与用法详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JAVA设计模式之访问者模式。分享给大家供大家参考,具体如下: 访问者模式: 一个作用于某对象结构中各元素的操作,使你可以在不改变各元素类数据结构的前提下增加作用于这些元素的新操作。 结构对象是访问者模式必备条件,且这个结构对象必须存在遍

  • 本文向大家介绍Android编程设计模式之访问者模式详解,包括了Android编程设计模式之访问者模式详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android编程设计模式之访问者模式。分享给大家供大家参考,具体如下: 一、介绍 访问者模式是一种将数据操作与数据结构分离的设计模式,它是《设计模式》中23种设计模式中最复杂的一个,但它的使用频率并不高,正如《设计模式》的作者GOF对访

  • 主要内容:介绍,实现,ComputerPart.java,Keyboard.java,Monitor.java,Mouse.java,Computer.java,ComputerPartVisitor.java,ComputerPartDisplayVisitor.java,VisitorPatternDemo.java在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行

  • 亦称: Visitor 意图 访问者模式是一种行为设计模式, 它能将算法与其所作用的对象隔离开来。 问题 假如你的团队开发了一款能够使用巨型图像中地理信息的应用程序。 图像中的每个节点既能代表复杂实体 (例如一座城市), 也能代表更精细的对象 (例如工业区和旅游景点等)。 如果节点代表的真实对象之间存在公路, 那么这些节点就会相互连接。 在程序内部, 每个节点的类型都由其所属的类来表示, 每个特定

  • 在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。 介绍 意图:主要将数据结构与数据操作分离。 主要解决:稳定的数据结构和易变的操作耦合问题。 何时使用:需要对一个对象结构中的对象进行