原型模式概念

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

  ⑴浅复制(浅克隆)

   被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。 Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址

  ⑵深复制(深克隆)

   被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

原型模式代码

package com.roc.prototype;

import java.io.Serializable;
/**
* 原型模式 程序员
* @author liaowp
*
*/
public class Programmer implements Serializable,Cloneable{ /**
*
*/
private static final long serialVersionUID = 3078949912404836178L; private String name; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Programmer clone() throws CloneNotSupportedException {
Programmer proto = (Programmer) super.clone();
return proto;
}
}

下面写一个浅复制的例子

package com.roc.prototype;
/**
* 地址
* @author liaowp
*
*/
public class Address{ private String province;//省 private String city;//市 public Address(String province,String city){
this.province=province;
this.city=city;
} public String getProvince() {
return province;
} public void setProvince(String province) {
this.province = province;
} public String getCity() {
return city;
} public void setCity(String city) {
this.city = city;
}
}
package com.roc.prototype;

/**
* 原型模式 程序员
* @author liaowp
*
*/
public class Programmer implements Cloneable{ private String name;//名字 private Address address; public Programmer(String name,Address address){
this.name=name;
this.address=address;
} public Address getAddress() {
return address;
} public void setAddress(Address address) {
this.address = address;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Object clone() throws CloneNotSupportedException {
Programmer proto = (Programmer) super.clone();
return proto;
} }
package com.roc.prototype;
/**
* 原型模式
* @author liaowp
*
*/
public class Client { public static void main(String[] args) throws CloneNotSupportedException {
//浅复制复制
Address address=new Address("jx","gz");
Programmer a=new Programmer("liaowp",address);
a.setAddress(new Address("jx", "gz"));
a.setName("liaowp");
Programmer b=(Programmer) a.clone();
b.setName("pwl");
b.getAddress().setProvince("bj");
System.err.println(b.getName()+b.getAddress().getProvince());
System.err.println(a.getName()+a.getAddress().getProvince());
}
}

  输出结果:pwlbj

liaowpbj

  可以看出来对象并复制,依然使用的是同一个引用。其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址。下面看深复制的写法,深复制有2种写法,一种是对象实现Cloneable,另外一种是二进制流。我都一起写了。

package com.roc.prototype;

/**
* 原型模式 程序员
* @author liaowp
*
*/
public class Programmer implements Cloneable{ private String name;//名字 private Address address; public Programmer(String name,Address address){
this.name=name;
this.address=address;
} public Address getAddress() {
return address;
} public void setAddress(Address address) {
this.address = address;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Object clone() throws CloneNotSupportedException {
Programmer proto = (Programmer) super.clone();
proto.address=(Address) address.clone();
     return proto;
} }
package com.roc.prototype;
/**
* 地址
* @author liaowp
*
*/
public class Address implements Cloneable{ private String province;//省 private String city;//市 public Object clone(){ Address address = null;
try {
address = (Address) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return address;
}
  public Address(String province,String city){
this.province=province;
this.city=city;
} public String getProvince() {
return province;
} public void setProvince(String province) {
this.province = province;
} public String getCity() {
return city;
} public void setCity(String city) {
this.city = city;
}     /* 深复制 */ 二进制的写法,需要类序列化

    public Object deepClone() throws IOException, ClassNotFoundException {

      /* 写入当前对象的二进制流 */
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(bos);
      oos.writeObject(this);

      /* 读出二进制流产生的新对象 */
      ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
      ObjectInputStream ois = new ObjectInputStream(bis);
      return ois.readObject();
  }

}

package com.roc.prototype;
/**
* 原型模式
* @author liaowp
*
*/
public class Client { public static void main(String[] args) throws CloneNotSupportedException {
//浅复制复制
Address address=new Address("jx","gz");
Programmer a=new Programmer("liaowp",address);
a.setAddress(new Address("jx", "gz"));
a.setName("liaowp");
Programmer b=(Programmer) a.clone();
b.setName("pwl");
b.getAddress().setProvince("bj");
System.err.println(b.getName()+b.getAddress().getProvince());
System.err.println(a.getName()+a.getAddress().getProvince());
}
}

结果:pwlbj

    liaowpjx

   拷贝还有2个知识点,对象拷贝时,类的构造函数是不会被执行的。一个实现了 Cloneable 并重写了 clone 方法的类 Programmer,有一个无参构造或有参构造 ,通过 new 关键字产生了一个对象 A,再然后通过 A.clone()方式产生了一个新的对象 T,那么在对象拷贝时构造函数是不会被执行的。即拷贝的过程中只执行一次构造方法。

  Clone 与 final 两对冤家。对象的 clone 与对象内的 final 属性是由冲突.在上面的Programmer类中修改为private final Address address;去掉get,set方法, proto.address=(Address) address.clone();这一句就会报错: proto.address=(Address) address.clone();final类型不能重新设置值。解决办法就是删除掉fina咯

  深拷贝和浅拷贝建议不要混合使用,一个类中某些引用使用深拷贝某些引用使用浅拷贝,这是一种非常差的设计,特别是是在涉及到类的继承,父类有几个引用的情况就非常的复杂,建议深拷贝和浅拷贝分开实现。

java设计模式之原型模式的更多相关文章

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

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

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

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

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

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

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

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

  5. JAVA 设计模式之 原型模式详解

    原型模式(Prototype Pattern)是指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 原型模式利用的是克隆的原理,创建新的对象,JDK提供的Cloneable 和JSON. ...

  6. JAVA设计模式之原型模式(prototype)

    原型模式: 原型模式又叫克隆模式 Java自带克隆模式 实现克隆模式必须实现Cloneable 接口,如果不实现会发生java.lang.CloneNotSupportedException异常 当某 ...

  7. 孙悟空的身外身法术使用了Java设计模式:原型模式

    目录 定义 意图 主要解决问题 何时使用 优缺点 结构 简单形式的原型模式 登记形式的原型模式 两种形式比较 浅克隆和深克隆 孙悟空的身外身法术 浅克隆实现 深克隆实现 定义 原型模式属于对象的创建型 ...

  8. 设计模式_11_原型模式(prototype)深拷贝、浅拷贝

    设计模式_11_原型模式(prototype) 浅拷贝: package designPatternOf23; /** * 定义:用原型实例,指定创建对象的种类,并通过拷贝这些原型创建新的对象 * P ...

  9. 【GOF23设计模式】原型模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_原型模式.prototype.浅复制.深复制.Cloneable接口  浅复制 package com.test.prot ...

随机推荐

  1. jQuery简洁大方的登录页面模板

    jQuery+CSS网站登录模板本模板带验证码 在线体验:http://hovertree.com/texiao/jquery/13.htm Demo 2:http://hovertree.com/h ...

  2. C# 洗牌算法

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精   C#洗牌算法如下: class Program { ...

  3. jQuery实现方式不一样的跳转到底部

    jQuery跳转到页面底部效果 在线体验:http://hovertree.com/texiao/jquery/9.htm 以下是完整HTML代码: <!DOCTYPE html> < ...

  4. Matlab 之 数据元素访问

    Matlab的含义是矩阵实验室,其特征之一就是数据的向量化操作,借此提升软件运行效率.那么,必然会涉及数据元素的访问.Matlab主要支持下面一些形式的访问: (1)array-inde: A(i) ...

  5. PHP流程控制之循环结构

    计算机程序最擅长的功能之一就是按规定的条件,重复执行某些操作.循环结构可以减少源程序重复书写的工作量,即在给定条件成立时,反复执行某程序段,直到条件不成立为止.给定的条件称为循环条件,反复执行的程序段 ...

  6. ABP之动态WebAPI(一)

    ABP的动态WebApi实现了直接对服务层的调用(其实病没有跨过ApiController,只是将ApiController公共化,对于这一点的处理类似于MVC,对服务端的 调用没有跨过HttpHan ...

  7. B-Tree索引在sqlserver和mysql中的应用

    在谈论数据库性能优化的时候,通常都会提到“索引”,但很多人其实并没有真正理解索引,也没有搞清楚索引为什么就能加快检索速度,以至于在实践中并不能很好的应用索引.事实上,索引是一种廉价而且十分有效的优化手 ...

  8. javascript如何设置DIV背景色为随机色

    随机色有两种格式: 效果预览:http://wjf444128852.github.io/DEMOLIST/JS/test/index.html 1.rgb(xxx,xxx,xxx) 2.#xxxxx ...

  9. iOS下Audio自动播放(Autoplay)音乐

    前几天做了一个H5活动页面,产品要求初始化播放音乐,因晓得H5 Audio标签支持Autoplay就没在意. 完了在手机上测试,发现手机上打开页面死活就是不会自动播放,点击播放按钮才可以播放,很是纠结 ...

  10. 可轮播滚动的Tab选项卡

    前段时间有试着搭建个后台主题ui框架,有用到可支持滚动的Tab选项卡,模仿着H+后台主题ui框架中的代码造轮子改造了下,可惜代码在公司,不能把代码外发出来(感觉这样被限制了很多,对于这样的公司没办法, ...