原型模式(Prototype)
我们先看看模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。==、我知道你们看了之后,会觉得copy一个对象?难道是换一下属性?在Java中,复制对象是通过clone()实现的。
我们看个例子:
package cs_prototype;
//原型类
public class Test_pro implements Cloneable{
@Override
public Object clone() throws CloneNotSupportedException{
Test_pro proto = (Test_pro) super.clone();
return proto;
}
}
我们看下代码很简单是吧!一个原型类Test_pro,先实现Cloneable接口,并且覆写clone方法,重要的是super.clone()调用的是Object的clone()方法,而在Object类中,clone()是native的。在这儿,我们先了解一下结合对象的浅复制和深复制。
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。
要实现深复制,需要采用流的形式读入当前对象的二进制输入,再写出二进制数据对应的对象。深浅复制的例子:
package cs_prototype;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Prototype implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private String string;
private SerializableObject obj;
/* 浅复制 */
public Object clone() throws CloneNotSupportedException {
Prototype proto = (Prototype) super.clone();
return proto;
}
/* 深复制 */
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();
}
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
public SerializableObject getObj() {
return obj;
}
public void setObj(SerializableObject obj) {
this.obj = obj;
}
}
class SerializableObject implements Serializable {
private static final long serialVersionUID = 1L;
}
上面的例子比较难理解,那我们换一个简单点的老样子先来个User类吧!相信大家已经很熟练了,name、pwd、sex、age四个属性,加一个toString方法
package cs_prototype;
public class User {
private String name;
private String pwd;
private String sex;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", pwd=" + pwd + ", sex=" + sex + ", age=" + age + "]";
}
}
我们再进行实现Cloneable接口和重写方法
@Override
public Object clone(){
User user = null;
try {
user=(User)super.clone();
user.name=this.name;
user.pwd=this.pwd;
user.sex=this.sex;
user.age=this.age;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return user;
}
...
User u1= new User();
u1.setName("狗哥");
u1.setPwd("123");
u1.setSex("男");
u1.setAge(22);
System.out.println(u1);
//进行复制
User u2 = (User) u1.clone();
u2.setName("德玛");
System.out.println(u2);
...
测试结果:
User [name=狗哥, pwd=123, sex=男, age=22]
User [name=德玛, pwd=123, sex=男, age=22]
是不是懂了一点这个原型模式,这样进行拷贝会显得异常的简单方便。