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指令面试题01-进程查看与终止
查看某一进程是否运行:ps -ef|grep 程序名 终止程序: kill pid 转载于:https://www.cnblogs.com/feihujiushiwo/p/10896636.html
- servlet温故知新
重新学习了一遍servlet-api的文档,做一些记录. 有道云的笔记直接复制到博客上格式会乱,因此直接放上有道云的链接:http://note.youdao.com/noteshare?id=915 ...
- C# 基础知识系列- 14 IO篇 文件的操作 (3)
本篇继续前两篇内容,跟大家介绍一下Path类以及FileSystemInfo这个类的主要方法和属性. 上文提到,在<C# 基础知识系列-IO篇>之文件相关的内容完结之后,会带领大家开发一个 ...
- Linux下文件完整性监控工具Tripwire详解
Tripwire 是目前最为著名的Unix下文件系统完整性检查的软件工具,这一软件采用的技术核心就是对每个要监控的文件产生一个数字签名,保留下来.当文件现在的数字签名与保留的数字签名不一致时,那么现在 ...
- 11.秋招复习简单整理之什么是ICMP协议,ICMP协议的功能是什么?
ICMP即 InternetControlMessageProtocol,是网络控制报文协议.它是TCP/IP协议族的一个子协议,用于在IP主机.路由器之间传递控制消息.控制消息指网络通不通.主机是否 ...
- Android EventBus踩坑,Activity接收不了粘性事件。
注解问题 EventBus 的 粘性事件,可以让 成功注册后的 Activity.Fragment 后再接收处理 这一事件. 但是今晚写代码时,突然发现粘性事件,发送不成功了.??? 具体情况是:我在 ...
- Spring AOP概述
一.AOP的基本概念: 首先先给出一段比较专业的术语: 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的 ...
- 使用Redis构建文章投票网站
涉及到的key: 1. article_time, 记录文章的发布时间,zset结构 2. article_score, 记录文章的得分, zset结构 得分 = 发布时间 + 投票用户数 X 432 ...
- 简单服务发现协议(SSDP)编程指导
本文主要讲解如何使用ssdp进行编程,不涉及过多关于ssdp的理论知识 1. 前言 网上对ssdp理论介绍的一大把,缺乏从编程角度的一个指导,这里不会长篇大论ssdp理论,只是根据实际编码经验对用 ...
- indexDB出坑指南
对于入了前端坑的同学,indexDB绝对是需要深入学习的. 本文针对indexDB的难点问题(事务和数据库升级)做了详细的讲解,而对于indexDB的特点和使用方法只简要的介绍了一下.如果你有一些使用 ...