原型模式:

  • 原型模式又叫克隆模式
  • 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)的更多相关文章

  1. java设计模式4——原型模式

    java设计模式4--原型模式 1.写在前面 本节内容与C++语言的复制构造函数.浅拷贝.深拷贝极为相似,因此建议学习者可以先了解C++的该部分的相关知识,或者学习完本节内容后,也去了解C++的相应内 ...

  2. 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)

    原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...

  3. JAVA 设计模式之原型模式

    目录 JAVA 设计模式之原型模式 简介 Java实现 1.浅拷贝 2.深拷贝 优缺点说明 1.优点 2.缺点 JAVA 设计模式之原型模式 简介 原型模式是六种创建型设计模式之一,主要应用于创建相同 ...

  4. java设计模式之原型模式

    原型模式概念 该模式的思想就是将一个对象作为原型,对其进行复制.克隆,产生一个和原对象类似的新对象.java中复制通过clone()实现的.clone中涉及深.浅复制.深.浅复制的概念如下: ⑴浅复制 ...

  5. 二十四种设计模式:原型模式(Prototype Pattern)

    原型模式(Prototype Pattern) 介绍用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象.示例有一个Message实体类,现在要克隆它. MessageModel usin ...

  6. java设计模式之五原型模式(Prototype)

    原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个对象作为原型,对其进行复制.克隆,产生一个和原对象类似的新对象.本小结会通过对象的复制,进行讲解.在Java中 ...

  7. JAVA设计模式之 原型模式【Prototype Pattern】

    一.概述: 使用原型实例指定创建对象的种类,而且通过拷贝这些原型创建新的对象. 简单的说就是对象的拷贝生成新的对象(对象的克隆),原型模式是一种对象创建型模式. 二.使用场景: 创建新的对象能够通过对 ...

  8. [设计模式] 4 原型模式 prototype

    设计模式:可复用面向对象软件的基础>(DP)本文介绍原型模式和模板方法模式的实现.首先介绍原型模式,然后引出模板方法模式. DP书上的定义为:用原型实例指定创建对象的种类,并且通过拷贝这些原型创 ...

  9. 设计模式 笔记 原型模式 prototype

    //---------------------------15/04/07---------------------------- //prototype 原型模式--对象创建型模式 /* 1:意图: ...

随机推荐

  1. CF1285 --- Dr. Evil Underscores

    CF1285 --- Dr. Evil Underscores 题干 Today as a friendship gift, Bakry gave Badawy \(n\) integers \(a_ ...

  2. PostgreSQL 10.0 preview 性能增强 - 分区表性能增强(plan阶段加速)

    标签 PostgreSQL , 10.0 , 分区表 , 子表 , 元信息搜索性能增强 背景 PostgreSQL 10.0 增强了分区表的子表搜索性能,对于涉及分区表包含子表特别多的QUERY,可以 ...

  3. 图论--最长路--洛谷P1807 最长路_NOI导刊2010提高(07)

    题目描述 设G为有n个顶点的有向无环图,G中各顶点的编号为1到n,且当为G中的一条边时有i < j.设w(i,j)为边的长度,请设计算法,计算图G中<1,n>间的最长路径. 输入格式 ...

  4. 一个epoll的简单例子

    epoll事件机制的触发方式有两种:LT(电平触发)和ET(边沿触发) EPOLLIN事件: 内核中的socket接收缓冲区 为空(低电平) 内核中的socket接受缓冲区 不为空(高电平) EPOL ...

  5. 惠普 HP Pavilion 15 Notebook PC清灰教程总结 惠普g4系列清灰加内存条教程

    最近天气热的电脑都受不了,风扇总是异响,声音很大,感觉是散热不行了,就把电脑清一下灰,虽然之前也清过,但是基本都忘记了,机子比较老,找不到具体教程,清灰过程中因为不熟悉有点费劲,手动记录一下,方便下次 ...

  6. 【Java8新特性】一张图带你领略Java8有哪些新特性

    写在前面 很多小伙伴留言说,冰河你能不能写一些关于Java8的文章呢,看书看不下去,看视频进度太慢.好吧,看到不少读者对Java8还是比较陌生的,那我就写一些关于Java8的文章吧,希望对大家有所帮助 ...

  7. 「从零单排HBase 09」Hbase的那些数据结构和算法

    在之前学习MySQL的时候,我们知道存储引擎常用的索引结构有B+树索引和哈希索引. 而对HBase的学习,也离不开索引结构的学习,它使用了一种LSM树((Log-Structured Merge-Tr ...

  8. redis-py中的坑

    今天发现,使用redis-py从redis中获取的数据竟然是加密的. conn = redis.Redis(host='redis_serverip', port=6379, password='re ...

  9. Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.

    今天上传图片遇到这个报错 百度了下,网上说是input标签type=file所以导致的问题,可是我的type=hidden 解决办法: 把上面的代码改成如下问题就解决了

  10. Oracle触发器之替代触发器

    替代触发器 替代视图增删改操作.视图可以认为成逻辑上的一张表,类似于把一个sql语句的执行结果永久的像表存储到数据 库中,视图一般用来做查询. 创建视图的语法: create view 视图名称 as ...