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:意图: ...
随机推荐
- 三、通过Vue基础属性做一个Table的增加、删除、姓名音位吗查询
html头文件包括css,和vue.js的文件的引用 <!DOCTYPE html> <html lang="en"> <head> <m ...
- Linux开发初探
坚持用了十几天的Linux操作系统,学会了很多的东西,但现在必须得抉择如何选择开发工具.在这些天的开发中,各种Linux下的IDE都有 所尝试.一向看好的Code::Blocks还是过于简单,用了一阵 ...
- Aurora: 来自 Amazon 的高性能的企业级关系数据库,兼容 MySQL
近日,在美国召开的AWS re:Invent云计算大会上,Amazon高级副总裁安迪·杰西发布了企业级关系数据库Aurora.Aurora是一个面向Amazon RDS(关系数据库服务).兼容MySQ ...
- Yii项目Security加密解密类提取
<?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * ...
- tr标签使用hover的box-shadow效果不生效
先说问题: 这是大致的HTML结构 <table cellpadding="0" cellspacing="0"> <thead> &l ...
- 《Docker从入门到跑路》之Dockerfile基本操作
一.简介 Dockerfile是一个文本文件,里面包含一条条指令,每一条指令就是一层镜像.一般情况下,Dockerfile分为4个部分: 基础镜像 维护者信息 镜像操作指令 容器启动时执行命令 例如: ...
- Nginx入门资料
最近在学习Nginx,记录一下自己的学习历程. 1. Nginx开发从入门到精通 (淘宝技术团队编写,值得一看) 2. <深入理解Nginx:模块开发与架构解析> 3. Nginx模块开发 ...
- C. Two Arrays(思维DP或组合数学)
\(首先很容易想到一个O(n^4m)的DP\) \(设dp\ [i]\ [j]\ [q]\ 为长度i,a数组以j结尾,b数组以q结尾(q>=j)\) for(int i=1;i<=n;i+ ...
- dp cf 20190615
A. Timofey and a tree 这个不算是dp,就是一个思维题,好难想的思维题,看了题解才写出来的, 把点和边分开,如果一条边的两个点颜色不同就是特殊边,特殊边两边连的点就叫特殊点, 如果 ...
- 【Hadoop离线基础总结】hive的窗口函数
hive的窗口函数 概述 hive中一般求取TopN时就需要用到窗口函数 专业窗口函数一般有三个 rank() over dense rank() over row_number() over 实例 ...