原型模式:

  • 原型模式又叫克隆模式
  • 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. Spring Boot 静态文件,请求不到,util文件夹

    静态文件貌似对util文件夹有特殊处理static/js/test.js 可以请求到static/js/laydate/test.js 可以请求到static/js/util/test.js 请求不到

  2. 13、canvas操纵像素数据ImageData

    2019独角兽企业重金招聘Python工程师标准>>> 一.ImageData 对象 含义: 存储canvas对象真实的像素数据(每个像素块的RGBA色值) 属性: 1.width: ...

  3. P1516 青蛙的约会和P2421 [NOI2002]荒岛野人

    洛谷 P1516 青蛙的约会 . 算是手推了一次数论题,以前做的都是看题解,虽然这题很水而且还交了5次才过... 求解方程\(x+am\equiv y+an \pmod l\)中,\(a\)的最小整数 ...

  4. 洛谷P1771 方程的解

    P1771 方程的解 都知道这个题可以用隔板法做 把这个\(g(x)\)想象为.....\(g(x)\)个苹果? 因为解是正整数,所以给这些"苹果"分组的时候每组最少有一个 然后我 ...

  5. auto_ptr和shared_ptr

    <Effective C++>在资源管理一节提到了智能指针,智能指针中最著名的当属auto_ptr和shared_ptr.本文主要研究两者的实现. auto_ptr的实现: templat ...

  6. 2-MyBatisPlus教程(HelloWorld)

    1,准备数据 DROP TABLE IF EXISTS user; CREATE TABLE user ( id ) NOT NULL COMMENT '主键ID', name ) NULL DEFA ...

  7. centos8-django项目部署 nginx+uwsgi

    1.虚拟环境virtualenv安装 1.安装virtualenv pip3 install virtualenv 2.创建目录,把项目文件传过来 mkdir My cd My 3.创建独立运行环境- ...

  8. springboot设置过滤器、监听器、拦截器

    其实这篇文章算不上是springboot的东西,我们在spring普通项目中也是可以直接使用的 设置过滤器: 以前在普通项目中我们要在web.xml中进行filter的配置,但是只从servlet 3 ...

  9. u-boot 移植(二)创建新平台的板级支持

    u-boot 移植(二)创建新平台的板级支持 soc:s3c2440 board:jz2440 uboot:u-boot-2016.11 toolchain:gcc-linaro-7.4.1-2019 ...

  10. (2)通信中为什么要进行AMC?

    AMC,Adaptive Modulation and Coding,自适应调制与编码. 通信信号的传输环境是变化不定的,信道环境时好时差.在这种情景下,我们不可能按照固定的MCS进行信号发送.假如信 ...