一模式定义
访问者模式:是表示一个作用于某对象结构中各个元素的操作,它使用户可以在不改变各元素类的前提下定义作用于这些元素的新操作。
二模式举例
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定义对象结构的类很少改变,但经常需要在此结构中定义新的操作。
五访问者模式静态类图
相关推荐
《算法和数据结构——左程云》是一份深入探讨算法与数据结构的资源包,由知名计算机科学家左程云编著。在这个压缩包中,我们可以期待找到一系列关于这两个核心计算机科学概念的详细讲解和实例。数据结构是编程的基础...
3. **栏目管理**:支持自定义网站的导航栏结构,灵活构建网站的层级结构,便于组织和分类信息。 4. **产品管理**:允许添加、修改和删除产品信息,包括产品图片、描述、参数等,方便客户浏览。 5. **在线留言/询盘**...
树结构模拟了现实中层级关系,如文件系统;图则用于表示复杂的关系网络,如社交网络或交通网络。 陈慧楠老师的课件中,会详细讲解这些数据结构的特性、操作以及它们在算法设计中的应用。例如,排序算法(如冒泡排序...
【广度优先搜索(BFS)】是一种在图或树中搜索节点的算法,它的主要特点是从根节点开始,按照层级顺序逐层遍历。在NOIP(全国信息学联赛)中,广度优先搜索是参赛者必须掌握的重要算法之一。 ### 1. 广度优先搜索的...
本项目“IOS应用源码——图层的滑动切换”提供了实现图层之间滑动切换的示例代码,旨在帮助开发者了解和掌握如何在iOS应用中动态地改变图层的内容和行为。 1. **图层基础** - 图层是UI视图的基础,负责处理视图的...
【标题】"Android源码——仿开心网源代码.7z"揭示了这是一份关于Android平台的应用程序源代码,其目标是模仿知名的社交网络平台——开心网。这份源码可能是为了教学、学习或者研究目的而创建的,帮助开发者了解如何...
GameData存储游戏数据,Layer和LayerList管理地图的层级结构。 10. **游戏界面模块**:GameView类主要负责游戏画面的绘制、声音播放等功能,DrawThread处理绘制任务。 11. **后台逻辑开发**:特别是怪物追踪算法的...
1. **文件浏览**:用户可以通过File Manager查看服务器上的文件夹结构,浏览不同层级的目录和文件。 2. **上传文件**:支持单个或批量上传文件,方便用户将本地文件上传至服务器。 3. **下载文件**:用户可以直接...
11. **代码结构与设计模式**:良好的代码组织和设计模式(如工厂模式、观察者模式)可以使项目更易于维护和扩展。 通过学习和实践这个【小小图片爬虫】项目,开发者不仅可以掌握HTTP请求的基本操作,还能了解到如何...
- **层次列表**:在工程资源管理器中,以层级结构展示所有文件,便于组织和导航。 通过深入学习和实践VB,无论是初学者还是有经验的程序员,都能快速掌握其基本概念和高级特性,创作出功能丰富的Windows应用程序。
树结构模拟了层级关系,广泛应用于文件系统、数据库索引等;图则用于表示复杂的关系网络,如路由选择、社交网络等;哈希表提供快速查找,通过哈希函数实现近似常数时间的插入和查找。 3. **排序与查找算法**:例如...
4. **自动目录与样式设置**:大型行政报告往往结构复杂,自动目录功能可以帮助快速生成层级清晰的目录,便于阅读和查找。同时,利用样式设置,可以确保文档中标题、正文、引用等格式的一致性。 5. **宏与VBA编程**...
本资源——"数据结构算法flash演示",通过生动的Flash动画形式,旨在帮助学习者深入理解这些抽象概念。以下是针对标题、描述以及标签所涉及的一些关键知识点的详细说明: **数据结构:** 数据结构是指在计算机中...
这份“数据结构教学课件”是针对该主题的配套教学资源,包含了赵仲孟教授的各章讲稿,为学习者提供了一个系统而全面的教材。 一、绪论 数据结构的学习首先要理解其基本概念,包括数据、数据元素、数据对象、数据...
《数据结构实验》是一本针对计算机科学和技术领域的实践教材,主要涵盖了软件网络技术中的核心概念——数据结构。数据结构是编程和算法设计的基础,它研究如何在计算机中组织和存储数据,以便高效地访问和修改这些...