原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

原型模式结构图

通俗来说:原型模式就是深拷贝和浅拷贝的实现。

浅拷贝

只实现了值拷贝,对于引用对象还是指向原来的对象。

  • 父类实现clone方法,子类没有实现clone方法,其效果是浅拷贝。
  • 父类实现clone方法,子类也实现clone方法,本来我想应该是深拷贝了,没想到也是浅拷贝
package com.prototype;
import java.io.Serializable; public class Work implements Serializable,Cloneable{
private static final long serialVersionUID = 207835812839542204L;
private String job;
private double salary;
public Work(String job,double salary) {
this.job = job;
this.salary = salary;
}
@Override
public String toString() {
return "Work [job=" + job + ", salary=" + salary + "]";
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
package com.prototype;

import java.io.Serializable;

public class User implements Serializable,Cloneable{
private static final long serialVersionUID = -2260332138558500447L; private String name = "";
private Work work = null; public User(String name,String job,double salary) {
this.name=name;
work = new Work(job, salary);
} public void changeJob(String job){
this.work.setJob(job);
}
/*只需要实现Cloneable接口,覆写clone方法,此处clone方法可以改成任意的名称,
因为Cloneable接口是个空接口,你可以任意定义实现类的方法名,如cloneA或者cloneB。
重点是super.clone()这句话,super.clone()调用的是Object的clone()方法,而在Object类中,clone()是native的。
*/
//浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
} @Override
public String toString() {
return "User [name=" + name + ", work=" + work + "]";
} }
package com.prototype;

public class Main {

    public static void main(String[] args) {
try {
User user1 = new User("zhangsan","ceo",100000);
User user2 = (User) user1.clone();
System.out.println(user1);
System.out.println(user2);
System.out.println("修改job");
user2.changeJob("cfo");
System.out.println(user1);
System.out.println(user2); } catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
//结果
User [name=zhangsan, work=Work [job=ceo, salary=100000.0]]
User [name=zhangsan, work=Work [job=ceo, salary=100000.0]]
修改job
User [name=zhangsan, work=Work [job=cfo, salary=100000.0]]
User [name=zhangsan, work=Work [job=cfo, salary=100000.0]]

深拷贝

即实现了值拷贝,也实现了对引用对象的拷贝。

  • 法一
    //深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。
//实现深复制,需要采用流的形式读入当前对象的二进制输入,再写出二进制数据对应的对象。
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();
}
  • 法二
    //将User的拷贝方法修改为下面的方法。
@Override
protected Object clone() throws CloneNotSupportedException {
Work w = (Work) work.clone();//对其引用变量进行拷贝
User u = (User)super.clone();//自身拷贝
u.work = w;//引用变量重新赋值。
return u;
}
===================================================
  • 定义

    用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。

  • 使用场景

    原型模式被用在频繁调用且极其相似的对象上,它会克隆对象并设置改变后的属性,而且消耗的资源较少。

  • 代码举例实现

ProtoTypeImpl.java

 package com.design.prototype;

public class ProtoTypeImpl implements Cloneable{

    private int shallowClone;

    private DeepClone deepClone = new DeepClone();

    public ProtoTypeImpl() {
System.out.println("construct is called");
} public void print() {
// TODO Auto-generated method stub
System.out.println(shallowClone);
System.out.println(deepClone.getS());
} @Override
protected ProtoTypeImpl clone(){
// TODO Auto-generated method stub
try{
ProtoTypeImpl protoTypeImp = (ProtoTypeImpl) super.clone();
//protoTypeImp.shallowClone = this.shallowClone;
//protoTypeImp.deepClone = this.deepClone.clone();
return protoTypeImp;
}catch(Exception e){
e.printStackTrace();
return null;
} } public void setShallowClone(int shallowClone) {
this.shallowClone = shallowClone;
} public void setS(String s){
deepClone.setS(s);
}
}

DeepClone.java

package com.design.prototype;

public class DeepClone implements Cloneable{
private String s; public String getS() {
return s;
} public void setS(String s) {
this.s = s;
} @Override
protected DeepClone clone(){
// TODO Auto-generated method stub
try {
return (DeepClone)super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}

App.java

package com.design.prototype;

public class App {

    public static void main(String[] args) {
// TODO Auto-generated method stub
ProtoTypeImpl protoTypeImp = new ProtoTypeImpl();
protoTypeImp.setShallowClone(1);
protoTypeImp.setS("deep clone");
protoTypeImp.print();
System.out.println("-------------");
ProtoTypeImpl protoTypeImp2 = protoTypeImp.clone();
protoTypeImp2.setShallowClone(2);
protoTypeImp2.setS("deep clone 2"); protoTypeImp2.print();
System.out.println("-------------");
protoTypeImp.print();
} }
  • 结果分析

运行结果1.png
  1. 这个现象主要是由于深浅复制引起的,普通类型的数据没有问题,而对象类型则有问题。同时我们应该注意到clone的时候构造函数是不会被调用的。

  2. 去掉ProtoTypeImpl.clone的两行注释(第一行没什么所谓,但是还是加上,有个对比)

    运行结果2.png
  3. 总结优缺点

    • 优点
      原型模式是在内存二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其点。
    • 缺点
      使用过程中要切记构造函数不会被调用,所以在构造函数完成的操作应该多加处理,还有深浅复制的问题

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

  1. 【设计模式】Java设计模式 - 原型模式

    [设计模式]Java设计模式 - 原型模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起 ...

  2. 我的Java设计模式-原型模式

    "不好意思,我是卧底!哇哈哈哈~"额......自从写了上一篇的观察者模式,就一直沉浸在这个角色当中,无法自拨.昨晚在看<使徒行者2>,有一集说到啊炮仗哥印钞票,我去, ...

  3. Java设计模式—原型模式

    原型设计模式是一种比较简单的设计模式,在项目中使用的场景非常多. 个人理解: 原型模式实现了对Java中某个对象的克隆功能,即该对象的类必须implements实现Cloneable接口来标识为可被克 ...

  4. Java设计模式-原型模式(Prototype)

    原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象.这就是选型模式的用意. 原型模式的结构 原型模式要求对象实现一个可以“克 ...

  5. 4.java设计模式-原型模式(prototype)

    在<JAVA与模式>一书中开头是这样描述原型(Prototype)模式的: 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更 ...

  6. Java设计模式原型模式

    原型模式: – 通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式. – 就是java中的克隆技术,以某个对象为原型,复制出新的对象.显然,新的对象具备原型对象的特点 – 优势 ...

  7. java设计模式——原型模式

    一. 定义与类型 定义:指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.不需要知道任何创建的细节,不调用构造函数 类型:创建型 二.使用场景 类初始化消耗较多资源 new 产生的一个对 ...

  8. PHP 设计模式 原型模式(Prototype)之深/浅拷贝

      看PHP 设计模式 原型模式(Prototype)时,衍生出一个扩展问题之 原型拷贝的浅拷贝和深拷贝问题(不管写Java还是写PHP还是写JS时都多多少少遇到过对象拷贝问题)   比如写前端页面时 ...

  9. 10. 星际争霸之php设计模式--原型模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

随机推荐

  1. JavaWeb学习笔记之JSP(二)

    1.1.  JSP的指令: 1.   什么是JSP 指令? JSP 指令: JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出, 而只是告诉引擎如何处理JSP页面中的 ...

  2. html网页代码各种名称及作用

    基本Web页文件<HTML><HEAD><TITLE></TITLE></HEAD><BODY></BODY>< ...

  3. 使用2to3转换python代码

    如果要把python2编译器下的代码转换升级到python3编译器,可以使用python自带的 2to3工具进行转化: windows下转化: doc 命令窗口: >> python  C ...

  4. uva 482 - Permutation Arrays

    <int, double> --> <int, string> 从而避免了输出格式: #include <vector> #include <strin ...

  5. windows Server 2003修改远程连接限制

    调整最大远程连接数: 1.开始->控制面板->添加或删除程序->添加/删除windows组件->选择“终端服务器”进行安装. 2.开始->运行->gpedit.ms ...

  6. Struts2+Spring4+Hibernate4整合超详细教程

    Struts2.Spring4.Hibernate4整合 超详细教程 Struts2.Spring4.Hibernate4整合实例-下载 项目目的: 整合使用最新版本的三大框架(即Struts2.Sp ...

  7. Java中 int和Integer的区别+包装类

    --今天用Integer 和Integer 比较 发现有问题,于是去查了查. 1.Java 中的数据类型分为基本数据类型和引用数据类型 int是基本数据类型,Integer是引用数据类型: Inget ...

  8. java动态缓存技术:WEB缓存应用(转)

    可以实现不等待,线程自动更新缓存 Java动态缓存jar包请下载. 源代码: CacheData.java 存放缓存数据的Bean /** *  */package com.cari.web.cach ...

  9. DEDE提高生成HTmL的速度

    1.找到include/inc/inc_fun_SpGetArcList.php打开之.   2.查找以下代码:   for($i=0;$i<$ridnum;$i++){     if($tps ...

  10. SpringMVC——从HelloWorld

    学习SpringMVC——从HelloWorld开始   前言: 时隔十二年,中国女排最终过关斩将,用3:1的成绩证明了自己的实力,霸气夺冠,为中国赢得了一枚意义非常的金牌.这是一次全民的狂欢,一场视 ...