JAVA设计模式之原型模式(prototype)
原型模式:
- 原型模式又叫克隆模式
- Java自带克隆模式
- 实现克隆模式必须实现Cloneable
- 接口,如果不实现会发生java.lang.CloneNotSupportedException异常
- 当某个类的属性已经设定好需要创建很多相同属性值的对象的时候使用clone模式非常方便
- 使用clone模式不见得比传统的new方式性能高
- 浅克隆和深克隆
先看下面的代码,没有实现Cloneable接口
package com.srr.dp.clone; /**
* (原型模式)克隆模式
*/
public class Appler /*implements Cloneable*/{ private String clor;
private int weight;
private int volume;
private StringBuilder descr; public Appler(String clor) {
this.clor = clor;
} @Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
} @Override
public String toString() {
return "Appler{" +
"clor='" + clor + '\'' +
", weight=" + weight +
", volume=" + volume +
", descr=" + descr +
'}';
}
} package com.srr.dp.clone; public class T {
public static void main(String[] args) throws CloneNotSupportedException { Appler appler = new Appler("yellow"); Appler appler1 = (Appler) appler.clone(); System.out.println(appler1);
}
}
运行结果:

浅拷贝:
package com.srr.dp.clone; /**
* (原型模式)克隆模式
* 浅拷贝
*/
public class Appler implements Cloneable { private String clor;
private int weight;
private int volume;
private Location loc; public Appler(String clor,int weight,int volume,Location loc) {
this.clor = clor;
this.weight = weight;
this.volume = volume;
this.loc = loc;
}
public String getClor() {
return clor;
} public void setClor(String clor) {
this.clor = clor;
} public int getWeight() {
return weight;
} public void setWeight(int weight) {
this.weight = weight;
} public int getVolume() {
return volume;
} public void setVolume(int volume) {
this.volume = volume;
} public Location getLoc() {
return loc;
} public void setLoc(Location loc) {
this.loc = loc;
} @Override
protected Object clone() throws CloneNotSupportedException {
//loc = (Locaton) loc.clone();
return super.clone();
} @Override
public String toString() {
return "Appler{" +
"clor='" + clor + '\'' +
", weight=" + weight +
", volume=" + volume +
", loc=" + loc +
'}';
}
} package com.srr.dp.clone; public class Location {
String name;
public Location(String name){
this.name = name;
} @Override
public String toString() {
return "Locaton{" +
"name='" + name + '\'' +
'}';
}
} package com.srr.dp.clone; /**
* 测试代码
*/
public class T {
public static void main(String[] args) throws CloneNotSupportedException {
Appler appler = new Appler("yellow",1,1,new Location("洛川"));
Appler appler1 = (Appler) appler.clone();
appler.setClor("red");
appler.getLoc().name = "宝鸡";
System.out.println("appler1 = "+appler1);
System.out.println("appler = "+appler);
}
}
运行结果:

从结果发现,当改变appler 的颜色还有location的值后,拷贝的apper1对象的颜色未发生改变但是location发生了改变。
这就是浅拷贝,引用对象无法保证拷贝之后完全独立只是拷贝了地址但是地址指向的对象是共享的,
虽然String类型也是引用类型但是共享常量池所以不会有这个问题。
那么如何让引用类型拷贝之后独立呢?
那么就要使用深拷贝请看如下代码:
package com.srr.dp.clone; /**
* (原型模式)克隆模式
* 浅拷贝
*/
public class Appler implements Cloneable { private String clor;
private int weight;
private int volume;
private Location loc; public Appler(String clor,int weight,int volume,Location loc) {
this.clor = clor;
this.weight = weight;
this.volume = volume;
this.loc = loc;
}
public String getClor() {
return clor;
} public void setClor(String clor) {
this.clor = clor;
} public int getWeight() {
return weight;
} public void setWeight(int weight) {
this.weight = weight;
} public int getVolume() {
return volume;
} public void setVolume(int volume) {
this.volume = volume;
} public Location getLoc() {
return loc;
} public void setLoc(Location loc) {
this.loc = loc;
} @Override
protected Object clone() throws CloneNotSupportedException {
Appler appler = (Appler)super.clone();
appler.loc = (Location) loc.clone();;
return appler;
} @Override
public String toString() {
return "Appler{" +
"clor='" + clor + '\'' +
", weight=" + weight +
", volume=" + volume +
", loc=" + loc +
'}';
}
} package com.srr.dp.clone; public class Location implements Cloneable{
String name;
public Location(String name){
this.name = name;
} @Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
} @Override
public String toString() {
return "Locaton{" +
"name='" + name + '\'' +
'}';
}
} package com.srr.dp.clone; /**
* 测试代码
*/
public class T {
public static void main(String[] args) throws CloneNotSupportedException {
Appler appler = new Appler("yellow",1,1,new Location("洛川"));
Appler appler1 = (Appler) appler.clone();
appler.setClor("red");
appler.getLoc().name = "宝鸡";
System.out.println("appler1 = "+appler1);
System.out.println("appler = "+appler);
}
}
运行结果:

从结果发现,当改变appler 的颜色还有location的值后,拷贝的apper1对象的颜色未发生改变location也发生了改变。
上面说到String类型的拷贝不存在浅拷贝的问题,那么StringBuilder或者StringBuffer呢,鉴于篇幅这里使用StringBuilder来举例
请看代码:
package com.srr.dp.clone; /**
* (原型模式)克隆模式
* 浅拷贝
*/
public class Appler implements Cloneable { private String color;
private int weight;
private int volume;
private Location loc; public String getColor() {
return color;
} public StringBuilder getDesc() {
return desc;
} public void setDesc(StringBuilder desc) {
this.desc = desc;
} private StringBuilder desc = new StringBuilder("好吃"); public Appler(String color,int weight,int volume,Location loc) {
this.color = color;
this.weight = weight;
this.volume = volume;
this.loc = loc;
}
public String getClor() {
return color;
} public void setColor(String color) {
this.color = color;
} public int getWeight() {
return weight;
} public void setWeight(int weight) {
this.weight = weight;
} public int getVolume() {
return volume;
} public void setVolume(int volume) {
this.volume = volume;
} public Location getLoc() {
return loc;
} public void setLoc(Location loc) {
this.loc = loc;
} @Override
protected Object clone() throws CloneNotSupportedException {
Appler appler = (Appler)super.clone();
appler.loc = (Location) loc.clone();
return appler;
} @Override
public String toString() {
return "Appler{" +
"color='" + color + '\'' +
", weight=" + weight +
", volume=" + volume +
", loc=" + loc +
", desc=" + desc +
'}';
}
} package com.srr.dp.clone; public class Location implements Cloneable{
String name;
public Location(String name){
this.name = name;
} @Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
} @Override
public String toString() {
return "Locaton{" +
"name='" + name + '\'' +
'}';
}
} package com.srr.dp.clone; /**
* 测试代码
*/
public class T {
public static void main(String[] args) throws CloneNotSupportedException {
Appler appler = new Appler("yellow",1,1,new Location("洛川"));
Appler appler1 = (Appler) appler.clone();
appler.getDesc().append("得不得了");
appler.getLoc().name = "宝鸡";
System.out.println("appler1 = "+appler1);
System.out.println("appler = "+appler);
}
}
运行结果:

这是是后你会发现当appler的desc值发生改变之后,apper1的值也发生改变了,说明StringBuilder的拷贝方式为浅拷贝,那么如何实现深拷贝呢
请看代码:
package com.srr.dp.clone; /**
* (原型模式)克隆模式
* 浅拷贝
*/
public class Appler implements Cloneable { private String color;
private int weight;
private int volume;
private Location loc; public String getColor() {
return color;
} public StringBuilder getDesc() {
return desc;
} public void setDesc(StringBuilder desc) {
this.desc = desc;
} private StringBuilder desc = new StringBuilder("好吃"); public Appler(String color,int weight,int volume,Location loc) {
this.color = color;
this.weight = weight;
this.volume = volume;
this.loc = loc;
}
public String getClor() {
return color;
} public void setColor(String color) {
this.color = color;
} public int getWeight() {
return weight;
} public void setWeight(int weight) {
this.weight = weight;
} public int getVolume() {
return volume;
} public void setVolume(int volume) {
this.volume = volume;
} public Location getLoc() {
return loc;
} public void setLoc(Location loc) {
this.loc = loc;
} @Override
protected Object clone() throws CloneNotSupportedException {
Appler appler = (Appler)super.clone();
appler.loc = (Location) loc.clone();
appler.desc = new StringBuilder(this.desc);
return appler;
} @Override
public String toString() {
return "Appler{" +
"color='" + color + '\'' +
", weight=" + weight +
", volume=" + volume +
", loc=" + loc +
", desc=" + desc +
'}';
}
} package com.srr.dp.clone; public class Location implements Cloneable{
String name;
public Location(String name){
this.name = name;
} @Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
} @Override
public String toString() {
return "Locaton{" +
"name='" + name + '\'' +
'}';
}
} package com.srr.dp.clone; /**
* 测试代码
*/
public class T {
public static void main(String[] args) throws CloneNotSupportedException {
Appler appler = new Appler("yellow",1,1,new Location("洛川"));
Appler appler1 = (Appler) appler.clone();
appler.getDesc().append("得不得了");
appler.getLoc().name = "宝鸡";
System.out.println("appler1 = "+appler1);
System.out.println("appler = "+appler);
}
}
运行结果:

这是是后你会发现当appler的desc值发生改变之后,apper1的值并没有发生改变。
写到这里原型模式就介绍完了。
原创不易,请多多支持!
JAVA设计模式之原型模式(prototype)的更多相关文章
- java设计模式4——原型模式
java设计模式4--原型模式 1.写在前面 本节内容与C++语言的复制构造函数.浅拷贝.深拷贝极为相似,因此建议学习者可以先了解C++的该部分的相关知识,或者学习完本节内容后,也去了解C++的相应内 ...
- 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)
原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...
- JAVA 设计模式之原型模式
目录 JAVA 设计模式之原型模式 简介 Java实现 1.浅拷贝 2.深拷贝 优缺点说明 1.优点 2.缺点 JAVA 设计模式之原型模式 简介 原型模式是六种创建型设计模式之一,主要应用于创建相同 ...
- java设计模式之原型模式
原型模式概念 该模式的思想就是将一个对象作为原型,对其进行复制.克隆,产生一个和原对象类似的新对象.java中复制通过clone()实现的.clone中涉及深.浅复制.深.浅复制的概念如下: ⑴浅复制 ...
- 二十四种设计模式:原型模式(Prototype Pattern)
原型模式(Prototype Pattern) 介绍用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象.示例有一个Message实体类,现在要克隆它. MessageModel usin ...
- java设计模式之五原型模式(Prototype)
原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个对象作为原型,对其进行复制.克隆,产生一个和原对象类似的新对象.本小结会通过对象的复制,进行讲解.在Java中 ...
- JAVA设计模式之 原型模式【Prototype Pattern】
一.概述: 使用原型实例指定创建对象的种类,而且通过拷贝这些原型创建新的对象. 简单的说就是对象的拷贝生成新的对象(对象的克隆),原型模式是一种对象创建型模式. 二.使用场景: 创建新的对象能够通过对 ...
- [设计模式] 4 原型模式 prototype
设计模式:可复用面向对象软件的基础>(DP)本文介绍原型模式和模板方法模式的实现.首先介绍原型模式,然后引出模板方法模式. DP书上的定义为:用原型实例指定创建对象的种类,并且通过拷贝这些原型创 ...
- 设计模式 笔记 原型模式 prototype
//---------------------------15/04/07---------------------------- //prototype 原型模式--对象创建型模式 /* 1:意图: ...
随机推荐
- 【Linux题目】第九关
前言:项目整合 企业项目实战考试: 1. 全网备份解决方案实战 2. NFS集群后段共享存储搭建优化 3. 解决NFS单点实现实时数据同步. 环境: 服务器角色 外网ip 内网ip 主机名 web 1 ...
- 获取系统DPI、系统显示比例等
using System; using System.Drawing; using System.Runtime.InteropServices; namespace XYDES { public c ...
- 打造livecd的注意事项
一:在CentOS.ks的定制脚本中,删除syslinux组件:出错提示: /usr/lib/python2.6/site-packages/imgcreate/errors.py:45: Depre ...
- RF(For 循环)
一.介绍:RobotFrameWork 支持 FOR 循环语句,语法和 Python 的语法基本相同,但 RobotFrameWork 中,"FOR" 关键字前面需要增加一个 &q ...
- spring bootweb综合开发的整理
1.json接口开发 当前开发中微服务的概念日渐深入人心,所以json数据交互可以带来的便利也不言而喻.在springboot中json数据的返回方式比较简单,只需要用@RestController注 ...
- 数据源管理 | 基于DataX组件,同步数据和源码分析
本文源码:GitHub·点这里 || GitEE·点这里 一.DataX工具简介 1.设计理念 DataX是一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL.Oracle等).HDF ...
- 关于MySQL数据库的卸载
首先对于MySQL这款数据库来讲,不能简单的卸载就草草了事,我们首先在mysql的文件下面找到my.ini这个文件, 在其中找到mysql数据库所产生的data文件,这个文件一般在c盘的一个隐藏目录下 ...
- Java 8 CompletableFuture思考
Java 8 CompletableFuture思考 最近一直在用响应式编程写Java代码,用的框架大概上有WebFlux(Spring).R2dbc.Akka...一些响应式的框架. 全都是Java ...
- spring mvc 实现文件上传
例:用户注册提交一个头像文件 第一步,创建项目 ,导入jar包 做文件上传除了要导入spring常规的jar包外,还要导入commons-fifileupload和commons-io这两个jar包. ...
- uniapp自定义简单省市区联动组件
又双叒一个uniapp组件 最近有一个选择地址的需求,就写了一个省市区联动选择器. 选择日期使用的picker,就照着它简单的整了一个,使用网络请求城市数据,还用到了vuex组件数据共享. 本来自己整 ...