设计模式之访问者模式(上)

访问者模式
1)概述
1.概念

访问者模式包含访问者被访问元素两个主要组成部分。

处方单中的各种药品信息就是被访问的元素,而划价人员和药房工作人员就是访问者,被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。

被访问元素通常不是单独存在的,它们存储在一个集合中,这个集合被称为对象结构,访问者通过遍历对象结构实现对其中存储的元素的逐个操作。

2.定义

提供一个作用于某对象结构中的各元素的操作表示,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

3.结构图

在这里插入图片描述

4.角色

Vistor(抽象访问者):抽象访问者为对象结构中每一个具体元素类ConcreteElement声明一个访问操作,从这个操作的名称或参数类型可以清楚知道需要访问的具体元素的类型,具体访问者需要实现这些操作方法,定义对这些元素的访问操作。

ConcreteVisitor(具体访问者):具体访问者实现了每个由抽象访问者声明的操作,每一个操作用于访问对象结构中一种类型的元素。

Element(抽象元素):抽象元素一般是抽象类或者接口,它定义一个accept()方法,该方法通常以一个抽象访问者作为参数。

ConcreteElement(具体元素):具体元素实现了accept()方法,在accept()方法中调用访问者的访问方法以便完成对一个元素的操作。

ObjectStructure(对象结构):对象结构是一个元素的集合,它用于存放元素对象,并且提供了遍历其内部元素的方法,可以结合组合模式来实现,也可以是一个简单的集合对象,如一个List对象或一个Set对象。

5.代码实现

抽象访问者类

abstract class Visitor{
	public abstract void visit(ConcreteElementA elementA);
	public abstract void visit(ConcreteElementB elementB);
	public void visit(ConcreteElementC elementC){
		//元素ConcreteElementC操作代码
	}
}

具体访问者类

class ConcreteVisitor extends Visitor{
	public void visit(ConcreteElementA elementA){
		//元素ConcreteElementA操作代码
	}
	
	public void visit(ConcreteElementB elementB){
		//元素ConcreteElementB操作代码
	}
}

抽象元素类

interface Element{
	public void accept(Visitor visitor);
}

具体元素类

class ConcreteElementA implements Element{
	public void accept(Visitor visitor){
		visitor.visit(this);
	}
	
	public void operationA(){
		//业务方法
	}
}

对象结构类

class ObjectStructure{
  //定义一个集合用于存储元素对象
	private ArrayList<Element> list = new ArrayList<Element>(); 
 
	public void accept(Visitor visitor){
		Iterator i=list.iterator();
		
		while(i.hasNext()){
		  //遍历访问集合中的每一个元素
			((Element)i.next()).accept(visitor); 
		}
	}
 
	public void addElement(Element element){
		list.add(element);
	}
 
	public void removeElement(Element element){
		list.remove(element);
	}
}
2)完整解决方案
1.结构图

在这里插入图片描述

FADepartment表示财务部,HRDepartment表示人力资源部,充当具体访问者角色,其抽象父类Department充当抽象访问者角色;EmployeeList充当对象结构,用于存储员工列表;FulltimeEmployee表示正式员工,ParttimeEmployee表示临时工,充当具体元素角色,其父接口Employee充当抽象元素角色。

2.代码实现
import java.util.*;
 
//员工类:抽象元素类
interface Employee{
	public void accept(Department handler); //接受一个抽象访问者访问
}
 
//全职员工类:具体元素类
@Data
class FulltimeEmployee implements Employee{
	private String name;
	private double weeklyWage;
	private int workTime;
 
	public FulltimeEmployee(String name,double weeklyWage,int workTime)
	{
		this.name = name;
		this.weeklyWage = weeklyWage;
		this.workTime = workTime;
	}	
 
	public void accept(Department handler){
		handler.visit(this); //调用访问者的访问方法
	}
}
 
//兼职员工类:具体元素类
@Data
class ParttimeEmployee implements Employee
{
	private String name;
	private double hourWage;
	private int workTime;
 
	public ParttimeEmployee(String name,double hourWage,int workTime)
	{
		this.name = name;
		this.hourWage = hourWage;
		this.workTime = workTime;
	}	
 
	public void accept(Department handler){
		handler.visit(this); //调用访问者的访问方法
	}
}
 
//部门类:抽象访问者类
abstract class Department{
  //声明一组重载的访问方法,用于访问不同类型的具体元素
	public abstract void visit(FulltimeEmployee employee);
	public abstract void visit(ParttimeEmployee employee);	
}
 
//财务部类:具体访问者类
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 + "元。");		
	}		
}
 
//人力资源部类:具体访问者类
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 + "小时。");
	}		
}
 
//员工列表类:对象结构
class EmployeeList
{
  //定义一个集合用于存储员工对象
	private ArrayList<Employee> list = new ArrayList<Employee>();
 
	public void addEmployee(Employee employee){
		list.add(employee);
	}
 
  //遍历访问员工集合中的每一个员工对象
	public void accept(Department handler){
		for(Object obj : list){
			((Employee)obj).accept(handler);
		}
	}
}

客户端类

public class Client{
	public static void main(String args[]){
		EmployeeList list = new EmployeeList();
		Employee fte1,fte2,fte3,pte1,pte2;
 
		fte1 = new FulltimeEmployee("张无忌",3200.00,45);
		fte2 = new FulltimeEmployee("杨过",2000.00,40);
		fte3 = new FulltimeEmployee("段誉",2400.00,38);
		pte1 = new ParttimeEmployee("洪七公",80.00,20);
		pte2 = new ParttimeEmployee("郭靖",60.00,18);
 
		list.addEmployee(fte1);
		list.addEmployee(fte2);
		list.addEmployee(fte3);
		list.addEmployee(pte1);
		list.addEmployee(pte2);
 
		Department dep;
		dep = new HRDepartment();
		list.accept(dep);
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/563465.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

上位机图像处理和嵌入式模块部署(树莓派4b处理类muduo网络编程)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 既然是linux编程&#xff0c;那么自然少不了网络编程。在linux平台上面&#xff0c;有很多的网络编程库可以选择&#xff0c;大的有boost、qt&…

免费PNG素材网站推荐:设计效率倍增!

一、即时设计 新一代协同设计工具即时设计&#xff0c;内置丰富社区资源&#xff0c;可以在此获得设计前线的各类PNG图像&#xff0c;以及矢量图标&#xff0c;包括毛玻璃、3D混搭、全息投影、单色、平面化等&#xff0c;都是符合目前市场的主流风格。通过最近更新、作品、资源…

影响钕铁硼磁钢性能的因素及方法

钕铁硼永磁材料自问世以来&#xff0c;就以其优越的磁性能而备受关注&#xff0c;被称为“磁王“&#xff0c;在市场需求的不断地增长下&#xff0c;钕铁硼生产工艺及磁体性能也不断发展和提升。我们一般用剩磁、矫顽力和最大磁能积这几个指标来衡量磁性材料的磁性能。 剩磁 B…

【C++】:类和对象(上)

目录 一&#xff0c;面向过程和面向对象初步认识二&#xff0c;类的引入三&#xff0c;类的定义3.1 **类的说明**3.2 **类的访问限定符**3.3 **类的两种实现方式**3.4 **成员变量的命名规则 --- 加下划线** 四&#xff0c;类的作用域4.1 **类域的说明**4.2 **类域与命名空间域的…

分析经过j2k压缩的dicom文件经验分享

最近碰到一个问题&#xff0c;在网上搜到是用JPEG 2000压缩的DICOM文件 JPEG 2000对应的transfer syntax UID为 1.2.840.10008.1.2.4.91 参考:https://dicom.nema.org/medical/dicom/current/output/chtml/part18/sect_8.7.3.html 该文件是用专业德国老牌开发库DCMTK生成的 (…

虚拟机VMware安装与Ubuntu

1.虚拟机安装 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;2fr6 CG54H-D8D0H-H8DHY-C6X7X-N2KG6 2.Ubuntu下载 Download Ubuntu Desktop | Ubuntu 3.设置 如后续要下一些软件越大越好

Diffusion Model原理剖析

目录 前言1. DDPM演算法初览2. 图像生成模型共同目标3. VAE: Lower bound of l o g P ( x ) logP(x) logP(x)4. Diffusion Model背后的数学原理5. 为什么需要Sample?6. Diffusion Model的应用7. Diffusion Model成功的关键总结参考 前言 接着上篇文章 图像生成模型浅析&#…

15.C++常用的算法_拷贝和替换算法

文章目录 遍历算法1. copy()代码工程运行结果 2. replace()代码工程运行结果 3. replace_if()代码工程运行结果 4. swap()代码工程运行结果 遍历算法 1. copy() 代码工程 copy()函数不要因为使用而使用#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include&l…

dremio支持设置

Dremio 支持提供可用于诊断目的的设置。这些设置通过 Dremio UI&#xff1a;设置>支持启用&#xff08;或禁用&#xff09; 使用 Client Tools 可以配置当用户查看数据集中的数据时&#xff0c;Dremio 项目的工具栏上显示哪些客户端应用程序按钮。用户可以通过单击相应的工具…

免费ssl泛域名/泛解析证书获取教程

泛域名SSL证书&#xff0c;也称为通配符证书&#xff0c;它可以保护一个主域名下的所有子域名。这意味着&#xff0c;无论你有多少个子域名&#xff0c;只要安装了一个泛域名SSL证书&#xff0c;就可以实现全部子域名的安全保护。这种证书非常适合大型企业或有大量子域名的网站…

数电复习(五)半导体存储电路

半导体存储电路 5.1 概述5.2 SR锁存器5.3 触发器5.3.1电平触发的触发器5.3.2 边沿触发器5.3.3 脉冲触发(主从) 触发器5.3.4 触发器逻辑功能的转换 5.4 寄存器5.4.1 数码寄存器5.4.2 移位寄存器 5.5 存储器5.5.1 ROM5.5.2 随机存储器RAM5.5.3 存储器容量的扩展5.5.4 用存储器实现…

怎么申请免费SSL证书,如何安装

什么是SSL证书&#xff0c;SSL&#xff0c;即Secure Sockets Layer&#xff08;安全套接层&#xff09;&#xff0c;它是一种安全协议&#xff0c;用于在互联网通信中为数据提供加密保护&#xff0c;从而防止数据被窃听或篡改。而SSL证书则是由权威的数字证书认证机构&#xff…

数据结构面试常见问题:什么是哈希表?它的工作原理是什么?

哈希表的基本概念 在我们的日常生活中&#xff0c;我们经常需要存储和查找各种信息&#xff0c;这些信息可能是电话号码&#xff0c;地址&#xff0c;或者是商品的价格等等。这些信息的存储和查找&#xff0c;就像是我们在一个巨大的仓库中存放和寻找物品。这个仓库就是数据结…

机器学习中的过拟合问题及应对策略:深入剖析与实战指南

在机器学习的领域中&#xff0c;过拟合是一个普遍而又棘手的问题。过拟合指的是模型在训练数据上表现优秀&#xff0c;但在未知或测试数据上表现不佳的现象。这通常是因为模型过于复杂&#xff0c;以至于“记住”了训练数据的噪声和细节&#xff0c;而非学习其内在规律和结构。…

立创·实战派ESP32-C3开发板 with lv_micropython

一、lv_micropython对驱动芯片的支持 ESP32-C3开发板的Display drivers:ST7789&#xff0c;Input drivers:FT6336&#xff0c;从LVGL的官方文档了解到lv_micropython包含了这两颗IC的驱动。 参考文档&#xff1a; lv_micropython already contains these drivers: 链接:Micro…

使用Python进行容器编排Docker Compose与Kubernetes的比较

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 随着容器化技术的普及&#xff0c;容器编排成为了管理和部署容器化应用程序的重要环节。在容…

jBPM的介绍

一、简介 jBPM&#xff08;Java Business Process Management&#xff09;是一个开源的业务流程管理框架&#xff0c;用于管理和执行业务流程。它提供了一个可视化的流程设计器&#xff0c;可以创建、模拟和部署业务流程&#xff0c;并提供了灵活的流程执行引擎。 jBPM可以帮…

【Go语言快速上手(三)】数组, 切片与映射

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Go语言专栏⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Go语言知识   &#x1f51d;&#x1f51d; GO快速上手 1. 前言2. 数组详解3. 切…

中栈内联(THE MID-STACK INLINER)优化

THE MID-STACK INLINER 直译为“中栈内联”&#xff0c;属于一种更为新进的内联策略。内联&#xff08;InLining&#xff09;的工作原理是将对一个函数的调用展开为函数本身的代码&#xff0c;通过内联减少函数调用的开销&#xff0c;也给编译器带来进一步优化代码的机会。那么…

AI大模型探索之路-实战篇3:基于私有模型GLM-企业级知识库开发实战

文章目录 前言概述一、本地知识库核心架构回顾&#xff08;RAG&#xff09;1. 知识数据向量化2. 知识数据检索返回 二、大模型选择1. 模型选择标准2. ChatGLM3-6B 三、Embedding模型选择四、改造后的技术选型五、资源准备1. 安装git-lfs2. 下载GLM模型3. 下载Embeding模型 六、…