简历复印--原型模式

1.1 夸张的简历

        简历的打印。"对编程来说,简单的复制粘贴极有可能造成重复代码的灾难。我所说的意思你根本还没听懂。那就以刚才的例子,我出个需求你写写看,要求有一个简历类,必须要有姓名,可以设置性别和年龄,可以设置工作经历。最终我需要写三份简历。"

1.2 简历代码初步实现

package code.chapter9.prototype1;

public class Test {

	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

		Resume resume1 = new Resume("大鸟");
		resume1.setPersonalInfo("男","29");
		resume1.setWorkExperience("1998-2000","XX公司");
		
		Resume resume2 = new Resume("大鸟");
		resume2.setPersonalInfo("男","29");
		resume2.setWorkExperience("1998-2000","XX公司");
		
		Resume resume3 = new Resume("大鸟");
		resume3.setPersonalInfo("男","29");
		resume3.setWorkExperience("1998-2000","XX公司");

		resume1.display();
		resume2.display();
		resume3.display();


		System.out.println();
		System.out.println("**********************************************");

	}
}

//简历类
class Resume  {
	private String name;
	private String sex;
	private String age;
	private String timeArea;
	private String company;

	public Resume(String name){
		this.name=name;
	}

	//设置个人信息
	public void setPersonalInfo(String sex,String age){
		this.sex=sex;
		this.age=age;
	}

	//设置工作经历
	public void setWorkExperience(String timeArea,String company){
		this.timeArea=timeArea;
		this.company=company;
	}

	//展示简历
	public void display(){
		System.out.println(this.name +" "+this.sex +" "+this.age);
		System.out.println("工作经历 "+this.timeArea +" "+this.company);
	}
}




        "很好,这其实就是当年我手写简历的时代的代码。三份简历需要三次实例化。你觉得这样的客户端代码是不是很麻烦?如果要二十份,你就需要二十次实例化。""是呀,而且如果我写错了一个字,比如1998年改成1999年,那就要改二十次。""你为什么不这样写呢?

package code.chapter9.prototype2;

public class Test {

	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

		Resume resume1 = new Resume("大鸟");
		resume1.setPersonalInfo("男","29");
		resume1.setWorkExperience("1998-2000","XX公司");
		
		Resume resume2 = resume1;
		
		Resume resume3 = resume1;

		resume1.display();
		resume2.display();
		resume3.display();


		System.out.println();
		System.out.println("**********************************************");

	}
}

//简历类
class Resume  {
	private String name;
	private String sex;
	private String age;
	private String timeArea;
	private String company;

	public Resume(String name){
		this.name=name;
	}

	//设置个人信息
	public void setPersonalInfo(String sex,String age){
		this.sex=sex;
		this.age=age;
	}

	//设置工作经历
	public void setWorkExperience(String timeArea,String company){
		this.timeArea=timeArea;
		this.company=company;
	}

	//展示简历
	public void display(){
		System.out.println(this.name +" "+this.sex +" "+this.age);
		System.out.println("工作经历 "+this.timeArea +" "+this.company);
	}
}

        "哈,这其实是传引用,而不是传值,这样做就如同是在resume2纸张和resume3纸张上写着简历在resume1处一样,没有实际的内容。"

1.3 原型模式

原型模式(Prototype),用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。[DP]

原型模式(Prototype)结构图

"原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。我们来看看基本的原型模式代码。"

package code.chapter9.prototype0;

public class Test {

	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

		ConcretePrototype p1 = new ConcretePrototype("编号123456");
		System.out.println("原ID:"+ p1.getID());

		ConcretePrototype c1 = (ConcretePrototype)p1.clone();
		System.out.println("克隆ID:"+ c1.getID());

		System.out.println();
		System.out.println("**********************************************");

	}
}

//原型类
abstract class Prototype implements Cloneable {
	private String id;

	public Prototype(String id){
		this.id=id;
	}

	public String getID(){
		return this.id;
	}

	//原型模式的关键就是有这样一个clone方法
	public Object clone(){
		Object object = null;
		try {
			object = super.clone();
		}
		catch(CloneNotSupportedException exception){
			System.err.println("Clone异常。");
		}
		return object;
	}
}

//具体原型类
class ConcretePrototype extends Prototype{

	public ConcretePrototype(String id){
		super(id);
	}

}



        "哦,这样就可以不用实例化ConcretePrototype了,直接克隆就行了?
        "说得没错,就是这样的。但对于Java而言,那个原型抽象类Prototype是用不着的,因为克隆实在是太常用了,所以Java提供了Cloneable接口,其中就是唯一的一个方法clone(),这样你就只需要实现这个接口就可以完成原型模式了。现在明白了?去改我们的'简历原型'代码吧。"

1.4 简历的原型实现

package code.chapter9.prototype3;

public class Test {

	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

		Resume resume1 = new Resume("大鸟");
		resume1.setPersonalInfo("男","29");
		resume1.setWorkExperience("1998-2000","XX公司");
		
		Resume resume2 = resume1.clone();
		resume2.setWorkExperience("2000-2003","YY集团");
		
		Resume resume3 = resume1.clone();
		resume3.setPersonalInfo("男","24");

		resume1.display();
		resume2.display();
		resume3.display();


		System.out.println();
		System.out.println("**********************************************");

	}
}

//简历类
class Resume implements Cloneable {
	private String name;
	private String sex;
	private String age;
	private String timeArea;
	private String company;

	public Resume(String name){
		this.name=name;
	}

	//设置个人信息
	public void setPersonalInfo(String sex,String age){
		this.sex=sex;
		this.age=age;
	}

	//设置工作经历
	public void setWorkExperience(String timeArea,String company){
		this.timeArea=timeArea;
		this.company=company;
	}

	//展示简历
	public void display(){
		System.out.println(this.name +" "+this.sex +" "+this.age);
		System.out.println("工作经历 "+this.timeArea +" "+this.company);
	}

	//实现了clone接口方法
	public Resume clone(){
		Resume object = null;
		try {
			object = (Resume)super.clone();
		}
		catch(CloneNotSupportedException exception){
			System.err.println("Clone异常。");
		}
		return object;
	}
}

        这样一来,客户端的代码就清爽很多了,而且你要是想改某份简历,只需要对这份简历做一定的修改就可以了,不会影响到其他简历,相同的部分就不用再重复了。不过不知道这样子对性能是不是有大的提高呢?"
        "当然是大大提高,你想呀,每new一次,都需要执行一次构造函数,如果构造函数的执行时间很长,那么多次执行这个初始化操作就实在太低效了。一般在初始化的信息不发生变化的情况下,克隆是最好的办法。这既隐藏了对象创建的细节,又对性能是大大的提高,何乐而不为呢?"
        "的确,我开始也没感觉到它的好,听你这么一说,感觉这样做的好处还真不少,它等于是不用重新初始化对象,而是动态地获得对象运行时的状态。这个模式真的很不错。

1.5 浅复制与深复制

        "别高兴得太早,如果我现在要改需求,你就又头疼了。你现在'简历'对象里的数据都是String型的,而String是一种拥有值类型特点的特殊引用类型,super.clone()方法是这样,如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其副本引用同一对象。什么意思呢?就是说如果你的'简历'类当中有对象引用,那么引用的对象数据是不会被克隆过来的。"
        "没太听懂,为什么不能一同复制过来呢?"

        "举个例子你就明白了,你现在的'简历'类当中有一个'设置工作经历'的方法,在现实设计当中,一般会再有一个'工作经历'类,当中有'时间区间'和'公司名称'等属性,'简历'类直接调用这个对象即可。

代码结构图

package code.chapter9.prototype4;

public class Test {

	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

		Resume resume1 = new Resume("大鸟");
		resume1.setPersonalInfo("男","29");
		resume1.setWorkExperience("1998-2000","XX公司");
		
		Resume resume2 = resume1.clone();
		resume2.setWorkExperience("2000-2003","YY集团");
		
		Resume resume3 = resume1.clone();
		resume3.setPersonalInfo("男","24");
		resume3.setWorkExperience("2003-2006","ZZ公司");

		resume1.display();
		resume2.display();
		resume3.display();


		System.out.println();
		System.out.println("**********************************************");

	}
}

//简历类
class Resume implements Cloneable {
	private String name;
	private String sex;
	private String age;
	private WorkExperience work;		//声明一个工作经历的对象
	public Resume(String name){
		this.name = name;
		this.work = new WorkExperience();//对这个工作经历对象实例化
	}
	//设置个人信息
	public void setPersonalInfo(String sex,String age){
		this.sex=sex;
		this.age=age;
	}
	//设置工作经历
	public void setWorkExperience(String timeArea,String company){
		this.work.setTimeArea(timeArea);//给工作经历实例的时间范围赋值
		this.work.setCompany(company);	//给工作经历实例的公司赋值
	}
	//展示简历
	public void display(){
		System.out.println(this.name +" "+this.sex +" "+this.age);
		System.out.println("工作经历 "+this.work.getTimeArea() +" "+this.work.getCompany());
	}
	public Resume clone(){
		Resume object = null;
		try {
			object = (Resume)super.clone();
		}
		catch(CloneNotSupportedException exception){
			System.err.println("Clone异常。");
		}
		return object;
	}
}

//工作经历类
class WorkExperience {

	//工作时间范围
	private String timeArea;
	public String getTimeArea(){
		return this.timeArea;
	}
	public void setTimeArea(String value){
		this.timeArea=value;
	}

	//所在公司
	private String company;
	public String getCompany(){
		return this.company;
	}
	public void setCompany(String value){
		this.company=value;
	}
}






        结果显示,实际结果与期望结果并不符合,前两次的工作经历数据被最后一次数据给覆盖了。

        "通过写代码,并且去查了一下Java关于Cloneable的帮助,我大概知道你的意思了,由于它是浅表复制,所以对于值类型,没什么问题,对引用类型,就只是复制了引用,对引用的对象还是指向了原来的对象,所以就会出现我给resume1、resume2、resume3三个引用设置'工作经历',但却同时看到三个引用都是最后一次设置,因为三个引用都指向了同一个对象。"
        "你写的和说的都很好,就是这个原因,这叫作'浅复制',被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。但我们可能更需要这样的一种需求,把要复制的对象所引用的对象都复制一遍。比如刚才的例子,我们希望是resume1、resume2、resume3三个引用的对象是不同的,复制时就一变二,二变三,此时,我们就叫这种方式为'深复制',深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。"
        "那如果'简历'对象引用了'工作经历','工作经历'再引用'公司','公司'再引用'职位'……这样一个引用一个,很多层,如何办?"
        "这的确是个很难回答的问题,深复制要深入到多少层,需要事先就考虑好,而且要当心出现循环引用的问题,需要小心处理,这里比较复杂,可以慢慢研究。就现在这个例子,问题应该不大,深入到第一层就可以了。"

1.6 简历的深复制实现

代码结构图

package code.chapter9.prototype5;

public class Test {

	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

		Resume resume1 = new Resume("大鸟");
		resume1.setPersonalInfo("男","29");
		resume1.setWorkExperience("1998-2000","XX公司");
		
		Resume resume2 = resume1.clone();
		resume2.setWorkExperience("2000-2003","YY集团");
		
		Resume resume3 = resume1.clone();
		resume3.setPersonalInfo("男","24");
		resume3.setWorkExperience("2003-2006","ZZ公司");

		resume1.display();
		resume2.display();
		resume3.display();


		System.out.println();
		System.out.println("**********************************************");

	}
}

//简历类
class Resume implements Cloneable {
	private String name;
	private String sex;
	private String age;
	private WorkExperience work;
	public Resume(String name){
		this.name = name;
		this.work = new WorkExperience();
	}
	//设置个人信息
	public void setPersonalInfo(String sex,String age){
		this.sex=sex;
		this.age=age;
	}
	//设置工作经历
	public void setWorkExperience(String timeArea,String company){
		this.work.setTimeArea(timeArea);//给工作经历实例的时间范围赋值
		this.work.setCompany(company);	//给工作经历实例的公司赋值
	}
	//展示简历
	public void display(){
		System.out.println(this.name +" "+this.sex +" "+this.age);
		System.out.println("工作经历 "+this.work.getTimeArea() +" "+this.work.getCompany());
	}
	public Resume clone(){
		Resume object = null;
		try {
			object = (Resume)super.clone();
			object.work = this.work.clone();
		}
		catch(CloneNotSupportedException exception){
			System.err.println("Clone异常。");
		}
		return object;
	}
}

//工作经历类
class WorkExperience implements Cloneable {
	//工作时间范围
	private String timeArea;
	public String getTimeArea(){
		return this.timeArea;
	}
	public void setTimeArea(String value){
		this.timeArea=value;
	}

	//所在公司
	private String company;
	public String getCompany(){
		return this.company;
	}
	public void setCompany(String value){
		this.company=value;
	}

	public WorkExperience clone(){
		WorkExperience object = null;
		try {
			object = (WorkExperience)super.clone();
		}
		catch(CloneNotSupportedException exception){
			System.err.println("Clone异常。");
		}
		return object;
	}
}






1.7 复制简历vs.手写求职信

"如果是写代码,我当然会鼓励你去应用原型模式简化代码,优化设计。但对于求职,你是愿意你的简历和求职信倍受重视呢?还是愿意和所有的毕业生一样千篇一律毫无新意地碰运气?"

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

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

相关文章

第十四届蓝桥杯省赛大学C组(C/C++)填充

原题链接:填充 有一个长度为 n 的 01 串,其中有一些位置标记为 ?,这些位置上可以任意填充 0 或者 1,请问如何填充这些位置使得这个 01 串中出现互不重叠的 0 和 1 子串最多,输出子串个数。 输入格式 输入一行包含一…

SQLite 4.9的 OS 接口或“VFS”(十三)

返回:SQLite—系列文章目录 上一篇:SQLite字节码引擎(十二) 下一篇:SQLite 4.9的虚拟表机制(十四) 1. 引言 本文介绍了 SQLite OS 可移植性层或“VFS” - 模块位于 SQLite 实现堆栈底部 提供跨操作系统的可移植性。 VFS是Virtual File…

5560.树的直径

蛮不错的一道题目&#xff0c;你要利用树的性质分析出&#xff0c;你只需要维护上一次的树的直径的两个端点就好了 #include<iostream>using namespace std; using ll long long; using pii pair<int,int>; const int N 6e510; const int inf 0x3f3f3f3f; cons…

算法:树形dp(树状dp)

文章目录 一、树形DP的概念1.基本概念2.解题步骤3.树形DP数据结构 二、典型例题1.LeetCode&#xff1a;337. 打家劫舍 III1.1、定义状态转移方程1.2、参考代码 2.ACWing&#xff1a;285. 没有上司的舞会1.1、定义状态转移方程1.2、拓扑排序参考代码1.3、dfs后序遍历参考代码 一…

MySQL复制拓扑4

文章目录 主要内容一.启用GUID并配置循环复制1.其中&#xff0c;UUID用来唯一标识每一个服务器&#xff0c;事务的编号记录了在该服务器上执行的事务的顺序。使用SELECT server_uuid\G命令可以查看服务器的UUID&#xff0c;sever1的UUID值显示如下&#xff1a;代码如下&#xf…

Vue3_2024_7天【回顾上篇watch常见的后两种场景】

随笔&#xff1a;这年头工作不好找咯&#xff0c;大家有学历提升的赶快了&#xff0c;还有外出人多注意身体&#xff0c;没错我在深圳这边阳了&#xff0c;真的绝啊&#xff0c;最尴尬的还给朋友传染了&#xff01;&#xff01;&#xff01; 之前三种的监听情况&#xff0c;监听…

文本识别 OCR 解决方案

Capture2Text 便携式 OCR 工具 Capture2Text 能够使用键盘快捷键快速对屏幕的一部分进行 OCR。 默认情况下&#xff0c;生成的文本将保存到剪贴板。支持中文、英文、法文、德文、日文、韩文、俄文、西班牙文等 90 多种语言。 Capture2Text 是便携式工具&#xff0c;不需要安装…

快速了解FastAPI与Uvicorn是什么?

概念 什么是Uvicorn Python Uvicorn 是一个快速的 ASGI&#xff08;Asynchronous Server Gateway Interface&#xff09;服务器&#xff0c;用于构建异步 Web 服务。它基于 asyncio 库&#xff0c;支持高性能的异步请求处理&#xff0c;适用于各种类型的 Web 应用程序。 Uvi…

SEO超级外链工具源码

源码简介 超级外链工具&#xff0c;是一款在线全自动化发外链的推广工具。使用本工具可免费为网站在线批量增加外链&#xff0c;大大提高外链发布工作效率&#xff0c;是广大草根站长们必备的站长工具。 搭建环境 PHP 5.6 安装教程 上传源码压缩包到网站目录并解压即可 首…

Linux安装最新版Docker完整教程

参考官网地址&#xff1a;Install Docker Engine on CentOS | Docker Docs 一、安装前准备工作 1.1 查看服务器系统版本以及内核版本 cat /etc/redhat-release1.2 查看服务器内核版本 uname -r这里我们使用的是CentOS 7.6 系统&#xff0c;内核版本为3.10 1.3 安装依赖包 …

【数据结构(二)】顺序表与ArrayList

❣博主主页: 33的博客❣ ▶文章专栏分类:数据结构◀ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;关注我带你学更多数据结构知识 目录 1.前言2.定义IList接口3.MyArraylist实现接口3.1定义成员变量与构造方法3.2添加元素3.3…

构建未来数字化世界的统一用户中心产品架构

随着数字化时代的到来&#xff0c;用户数据管理变得愈发复杂&#xff0c;各类应用和服务的涌现使得用户信息分散存储&#xff0c;导致了数据孤岛和体验碎片化的问题。在这样的背景下&#xff0c;统一用户中心产品架构应运而生&#xff0c;为构建数字化世界提供了全新的解决方案…

S7-200 SMART 应用第003期-数字量输入模块接线

概述 S7-200 SMART作为西门子的一款高性价比PLC产品,很多工控电气工程师在选型和电路图设计时,对模块接线并不是非常清楚,为了使大家更好的了解和掌握该部分,本文从CPU本体、数字量输入(DI)、数字量输出(DQ)向大家详细介绍S7-200 SMART 详细的接线和注意事项。 不同型号C…

2023年度总结:允许迷茫,破除迷茫;专注自身,把握当下

0、前言 &#x1f4dc;为什么24年已经过了几个月&#xff0c;才提笔写这年度总结呢&#xff1f;毫不羞愧直问我的内心&#xff0c;其实就是懒罢了。直到前几天朋友看到了我去年写的总结&#xff0c;我自己点进那篇总结&#xff0c;完完整整的看了一遍&#xff0c;又翻看我23年…

ideaSSM 网上选课管理系统bootstrap开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 idea 开发 SSM 网上选课管理系统是一套完善的信息管理系统&#xff0c;结合SSM框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff…

二分法题集1

1 二分查找 分析&#xff1a; 这是一道很简单的二分法题&#xff0c;定义两个指针和中间值middle&#xff0c;判断middle对应数组值与目标值的大小关系&#xff0c;从而对left和right进行修改。由于太过基础&#xff0c;代码简单基础就不多赘述。 目录 1 二分查找 分析&…

PyQt PySide6零基础入门与项目实战视频教程

目录 课程亮点课程大纲第一章&#xff1a;基础篇 PySide6开发环境安装第二章 控件与布局篇 PySide6常用控件与界面布局使用介绍第三章 信号槽与事件机制第四章 QMainWindow应用篇第五章 样式表qss与自定义控件第六章 图表与曲线第七章 数据库编程第八章 项目实战&#xff1a;高…

FJSP:小龙虾优化算法(Crayfsh optimization algorithm,COA)求解柔性作业车间调度问题(FJSP),提供MATLAB代码

一、柔性作业车间调度问题 柔性作业车间调度问题&#xff08;Flexible Job Shop Scheduling Problem&#xff0c;FJSP&#xff09;&#xff0c;是一种经典的组合优化问题。在FJSP问题中&#xff0c;有多个作业需要在多个机器上进行加工&#xff0c;每个作业由一系列工序组成&a…

二叉树的介绍

学习堆排序时先了解下二叉树&#xff0c;因为堆排序中使用了二叉树。 一、二叉树介绍 二叉树&#xff08;binary tree&#xff09;树的每个节点最多有2个孩子节点。注意&#xff0c;这里是最多有2个&#xff0c;也可能只有1个&#xff0c;或者没有孩子节点。 二叉树结构如图…

极客时间: 用 Word2Vec, LangChain, Gemma 模拟全本地检索增强生成(RAG)

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…