java.请写出一个原型模式_java原型模式

标签:

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

0980097848285f303768fbe2ca55ae5d.png

原型模式结构图

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

浅拷贝

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

父类实现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();

}

}

结果分析

3a4479024f39fb3970b1eba2331b0485.png

运行结果1.png

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

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

37cd7a0746d42c78442dc2aa8b999349.png

运行结果2.png

总结优缺点

优点

原型模式是在内存二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其点。

缺点

使用过程中要切记构造函数不会被调用,所以在构造函数完成的操作应该多加处理,还有深浅复制的问题

文/lguipeng(简书作者)

原文链接:http://www.jianshu.com/p/062023c33d77

著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

标签:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值