GOF23设计模式之:原型模式(ProtoType)
场景
-
思考一下:克隆技术是怎样的过程?克隆羊多莉大家还记得吗?
-
javascrip语言中,继承怎么实现?那里面也有prototype,大家还记得吗?
原型模式
-
通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
-
就是java中的克隆技术,以某个对象为原型,复制出新的对象.显然,
-
优势有:效率高(直接克隆,避免了重新执行构造过程步骤)
-
克隆类似于new,但是不同于new.new创建新的对象属性采用的是默认值.克隆出的对象的属性值完全和原型对象相同.并且克隆出的新对象改变不会影响原型对象.然后再修改克隆对象的值
原型模式实现
-
Cloneable接口可clone方法
-
Protype模式中实现起来最困难的地方就是内存复制操作,所幸Java中提供了clone()方法替我们做了绝大部分事情
import java.util.Date;
//1997年英国克隆羊多莉
public class Sheep implements Cloneable{
private String name;
private Date brithday;
public Sheep() {
// TODO Auto-generated constructor stub
}
public Sheep(String name, Date brithday) {
super();
this.name = name;
this.brithday = brithday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBrithday() {
return brithday;
}
public void setBrithday(Date brithday) {
this.brithday = brithday;
}
//重写Object的clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
import java.util.Date;
public class Client {
@SuppressWarnings("deprecation")
public static void main(String[] args) throws CloneNotSupportedException {
//浅克隆
Date d = new Date(183964743);
Sheep s1 = new Sheep("莉莉",d);
System.out.println(s1);
System.out.println(s1.getName());
System.out.println(d.getTime());
d.setDate(183974743);
System.out.println(d.getTime());
Sheep s2 = (Sheep) s1.clone();
System.out.println(s2);
System.out.println(s2.getName());
s2.setName("多莉");
System.out.println(s2.getName());
System.out.println(d.getTime());
}
}
import java.util.Date;
//1997年英国克隆羊多莉
public class Sheep implements Cloneable{
private String name;
private Date brithday;
public Sheep() {
// TODO Auto-generated constructor stub
}
public Sheep(String name, Date brithday) {
super();
this.name = name;
this.brithday = brithday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBrithday() {
return brithday;
}
public void setBrithday(Date brithday) {
this.brithday = brithday;
}
//重写Object的clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
//添加如下代码实现深复制
Sheep s = (Sheep)obj;
//把属性也进行克隆
s.brithday = (Date)this.brithday.clone();
return obj;
}
}
import java.util.Date;
/**
* 深复制
* @author Matrix42
*
*/
public class Client2 {
public static void main(String[] args) throws CloneNotSupportedException {
Date d = new Date(183964743);
Sheep s1 = new Sheep("莉莉",d);
System.out.println(s1);
System.out.println(s1.getName());
System.out.println(s1.getBrithday());
Sheep s2 = (Sheep) s1.clone();
d.setTime(2222222222222L);
System.out.println(s1.getBrithday());
System.out.println(s2.getBrithday());
}
}
利用序列化和反序列化技术实现深克隆
短时间大量修改对象时,原型模式和普通new方式效率测试
- 创建对象比较耗时时大约提高1000倍左右
开发中的应用场景
-
原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone方法创建一个对象,然后由工厂方法提供给调用者
- spring中的bean的创建市级就是两种:单例模式和原型模式(原型模式需要和工厂模式搭配起来)
Sheep实现Serializable接口
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;
/**
* 使用序列化和反序列化实现深克隆
* @author Matrix42
*
*/
public class Client3 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Date d = new Date(183964743);
Sheep s1 = new Sheep("莉莉",d);
System.out.println(s1);
System.out.println(s1.getName());
System.out.println(s1.getBrithday());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(s1);
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
Sheep s2 = (Sheep) ois.readObject();
System.out.println(s2.getName());
}
}