简历复印--原型模式

news2024/10/9 10:19:41

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.手写求职信

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity类银河恶魔城学习记录12-2 p124 Character Stats UI源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_Statslot.cs using System.Collections; using System.Collections.Gen…

root@localhost‘s password: Permission denied, please try again.

编辑、etc/ssh/sshd_config文件 ,将PermitRootLogin这行改为yes rootubuntu:/home/ubuntu# vim /etc/ssh/sshd_config 重新加载改文件 /etc/init.d/ssh restart

uniapp 设置globalStyle navigationBarTitleText 不显示

设置全局的navigationBarTitleText但是没有显示 没效果: 原因: 这里实际上设置了navigationBarTitleText 为"" 所以不会使用全局的设置 解决方法就是直接将这一行代码删除

【逆向思考 】【拓扑排序】1591. 奇怪的打印机 II

本文涉及的知识点 逆向思考 拓扑排序 LeetCode1591. 奇怪的打印机 II 给你一个奇怪的打印机,它有如下两个特殊的打印规则: 每一次操作时,打印机会用同一种颜色打印一个矩形的形状,每次打印会覆盖矩形对应格子里原本的颜色。 一…

【教程】宝塔default.db占用空间几十g解决方法|宝塔占用磁盘空间特别大解决方法|宝塔磁盘被占满怎么清理

目录 一、前言二、排查问题三、解决方法 一、前言 用过宝塔创建网站,大家应该都非常熟悉,但是用随着用的时间越来越多,宝塔所占用的空间也越来越多,不停的加大数据盘都没有用,我原先买了30G够用了,随着时间…

基本数据类型、包装类与字符串间的转换

(1)基本数据类型转为字符串 方式1:调用字符串重载的valueOf()方法 int a 10; //String str a;//错误的String str String.valueOf(a);方式2:更直接的方式 int a 10;String str a "";(2)…

汽车EDI:如何与奔驰建立EDI连接?

梅赛德斯-奔驰是世界闻名的豪华汽车品牌,无论是技术实力还是历史底蕴都在全球汽车主机厂中居于领先位置。奔驰拥有多种车型,多元化的产品布局不仅满足了不同用户画像的需求,也对其供应链体系有着极大的考验。 本文将为大家介绍梅赛德斯-奔驰乘…

【深入理解计算机系统第3版】有符号数和无符号数转换以及移位运算练习题2.23

题目 考虑下面的C函数&#xff1a; int fun1(unsigned word) {return (int) ((word << 24) >> 24); }int fun2(unsigned word) {return ((int) word << 24) >> 24; } 假设一个采用补码运算的机器上以32位程序来执行这些函数。还假设有符号数值的右移…

代码随想录算法训练营第30天|LeetCode236.二叉树的最小公共祖先

代码随想录算法训练营第30天|LeetCode236.二叉树的最小公共祖先 1、LeetCode236.二叉树的最小公共祖先 236. 二叉树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 自底向上查找&#xff0c;有点难度&#xff01; | LeetCode&#xff1a;236. 二叉树的最近公共祖先_哔…

如何通过ArkTS卡片的Canvas自定义绘制能力实现五子棋游戏卡片

介绍 本示例展示了如何通过ArkTS卡片的Canvas自定义绘制能力实现一个简单的五子棋游戏卡片。 使用Canvas绘制棋盘和黑白棋子的落子。通过卡片支持的点击事件进行交互&#xff0c;让用户在棋盘上进行黑白棋子的对局。通过TS的逻辑代码实现五子棋输赢判定、回退等逻辑计算&…

7 X 24h智能安全运维再升级!Fortinet 全面集成全新 FortiGuard SOCaaS

数字化时代网络安全威胁层出不穷&#xff0c;网络犯罪分子的狡诈攻击手段不断翻新&#xff0c;传统安全防御手段亟需进化。更为棘手的是&#xff0c;网络安全专业人才的匮乏&#xff0c;让众多企业陷入安全运营的困境。为了有效应对这一挑战&#xff0c;Fortinet全新推出FortiG…

3DGS实时高质量大规模场景渲染最新SOTA!

作者&#xff1a;小柠檬 | 来源&#xff1a;3DCV 在公众号「3DCV」后台&#xff0c;回复「原论文」可获取论文pdf 添加微信&#xff1a;dddvision&#xff0c;备注&#xff1a;3D高斯&#xff0c;拉你入群。文末附行业细分群 详细内容请关注3DCV 3D视觉精品课程&#xff1a;…

Qt自定义控件之Battery电池控件

文章目录 前言一、BasicBattery二、Battery控件三、效果总结 前言 在Qt应用程序开发中&#xff0c;自定义控件是一种常见的需求&#xff0c;开发者经常需要根据特定的需求创建定制化的控件来增强用户界面的交互性和美观性。Battery电池控件是一种常见的自定义控件&#xff0c;…

Codeforces Round 932 (Div. 2) ---- F. Andrey‘s Tree ---- 题解

F. Andreys Tree&#xff1a; 题目描述&#xff1a; 思路解析&#xff1a; 我们假设删除任意一个结点后&#xff0c;我们会将整个树切分为k个联通块&#xff0c;那么可以明确的知道我们只需要连接(k-1)条边就可以将这k个联通块重新连为一棵树。 那么最小代价是啥呢? 图解分…

代码随想录day35--动态规划的应用2||01背包理论基础、携带研究材料

01背包理论基础 有n件物品和一个最多能背重量为w的背包。第i件物品的重量是weight[i],得到的价值为 value[i]。每件物品只能用一次&#xff0c;将这些物品装入背包里物品价值总和最大。 这是很标准的背包问题&#xff0c;很多同学看到后很自然的就想到了背包&#xff0c;我们…

ruoyi-nbcio-plus基于vue3的flowable流程设计器主界面升级修改

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…

链路追踪原理

分布式系统为什么需要链路追踪&#xff1f; 随着互联网业务快速扩展&#xff0c;软件架构也日益变得复杂&#xff0c;为了适应海量用户高并发请求&#xff0c;系统中越来越多的组件开始走向分布式化&#xff0c;如单体架构拆分为微服务、服务内缓存变为分布式缓存、服务组件通…

前视声呐目标识别定位(六)-代码解析之目标截图并传输

前视声呐目标识别定位&#xff08;一&#xff09;-基础知识 前视声呐目标识别定位&#xff08;二&#xff09;-目标识别定位模块 前视声呐目标识别定位&#xff08;三&#xff09;-部署至机器人 前视声呐目标识别定位&#xff08;四&#xff09;-代码解析之启动识别模块 …

leetcode刷题-代码训练营-第7章-回溯算法1

回溯法模板 void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择&#xff1a;本层集合中元素&#xff08;树中节点孩子的数量就是集合的大小&#xff09;) {处理节点;backtracking(路径&#xff0c;选择列表); // 递归回溯&#xff0c;撤销处理结果} }理解 从…

红蓝色WordPress外贸建站模板

红蓝色WordPress外贸建站模板 https://www.mymoban.com/wordpress/5.html