您的位置:首页 > 编程语言 > Java开发

java-设计模式(创建型)-【原型模式】

2015-04-13 11:56 686 查看
1.Prototype(原型模式)

定义:用原型实例指定创建对象的种类,并且通过克隆这些原型创建新的对象。

注意:这里的“克隆”,指的是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,

因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效

使用场景:

原型模式本质上就是对象的拷贝,使用对象拷贝代替对象创建的原因有很多。比如对象的初始化构造非常复杂,

消耗资源巨大;运行时对象状态变化不可重现;无法获得对象的成员的运行时值等

使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,

它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。

克隆满足的条件:

clone()方法将对象复制了一份并返还给调用者。所谓“复制”的含义与clone()方法是怎么实现的。一般而言,clone()方法满足以下的描述:

  (1)对任何的对象x,都有:x.clone()!=x。换言之,克隆对象与原对象不是同一个对象。

  (2)对任何的对象x,都有:x.clone().getClass() == x.getClass(),换言之,克隆对象与原对象的类型一样。

  (3)如果对象x的equals()方法定义其恰当的话,那么x.clone().equals(x)应当成立的。

   在JAVA语言的API中,凡是提供了clone()方法的类,都满足上面的这些条件。JAVA语言的设计师在设计自己的clone()方法时,

也应当遵守着三个条件。一般来说,上面的三个条件中的前两个是必需的,而第三个是可选的

浅克隆和深克隆:

浅复制:将一个对象复制后,基本数据类型的变量都会重新复制创建,而引用类型,指向的还是原对象所指向的。

深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的即引用类型的对象还会复制多一份。

注意这里涉及到复制的深度问题,你要复制多深,即引用对象的深度。

2.原型模式与抽象工厂模式区别



采用工厂模式:为每一个具体子类定义一个与其等级平行的工厂类,这样会变得重复累赘。

采用原型模式:将对象本身当做工厂,通过clone方法克隆出自己的副本。

3.浅克隆和深克隆





/*
* 一个原型类,只需要实现Cloneable接口,覆写clone方法,
* 此处clone方法可以改成任意的名称,因为Cloneable接口是个空接口,
* 你可以任意定义实现类的方法名,如cloneA或者cloneB,
* 因为此处的重点是super.clone()这句话,super.clone()调用的是Object的clone()方法,
* */
public class Prototype implements Cloneable {

//浅复制:需要用public修饰符覆写clone方法
public Object clone() throws CloneNotSupportedException
{
Prototype proto=(Prototype)super.clone();
return proto;
}
//深复制:将对象序列化入内存,再复制反序列化对象出来。
public Object deepclone() throws IOException, ClassNotFoundException
{
//使用ByteArray输入输出流(节点流)写入内存(目的地)里,
//使用Object输入输出流(处理流)将对象(源目标)写入。

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

//读取二进制流产生的新对象
byte[] buf=new byte[1024];
ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
Prototype pro=(Prototype)ois.readObject();
return pro;
}
}


4.图解



4.1 颜色原型及实现子类

//原型(接口)类,实现clonealbe接口
//指关心方法
public interface Prototype extends Cloneable{
public Prototype clonenew()throws CloneNotSupportedException;
public void display();
}
//颜色类,包含所有颜色,由初始化时定义该颜色和颜色值
class  ColorProto implements Prototype
{
private String colorName;
public String getColorName() {
return colorName;
}
public void setColorName(String colorName) {
this.colorName = colorName;
}

private int r;
private int g;
private int b;
public ColorProto (String colorName,int r,int g,int b)
{
this.colorName=colorName;
this.r=r;
this.g=g;
this.b=b;
}
//克隆自己
@Override
public ColorProto clonenew() throws CloneNotSupportedException {
// TODO Auto-generated method stub
ColorProto cp=(ColorProto) super.clone();
return cp;
}
//显示自己的颜色名和值
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println(colorName+":"+r+","+g+","+b);
}

}


 4.2 颜色管理器

//管理颜色类,具有添加,取出颜色种类的方法
public class ColorProManage {

private HashMap<String ,ColorProto> hm=new HashMap<String ,ColorProto>();

//放入颜色
public void putColor (ColorProto cp)
{
String colorName=cp.getColorName();
hm.put(colorName, cp);
}
//取出颜色
public ColorProto getColor(String colorName)
{
ColorProto cp=hm.get(colorName);
if(cp!=null)
return cp;
else
return null;
}
}


  4.3 测试

public class Test  {

public static void main(String[] args) throws Exception {

//新建颜色管理器
ColorProManage  cm=new ColorProManage();
//为颜色管理器添加颜色
ColorProto cp1=new ColorProto("red", 255, 0, 0);
ColorProto cp2=new ColorProto("green", 0, 255, 0);
ColorProto cp3=new ColorProto("blue",0, 0, 255);
cm.putColor(cp1);
cm.putColor(cp2);
cm.putColor(cp3);
//克隆出颜色管理器里的红色
ColorProto cpclone= cm.getColor("red").clonenew();
cpclone.display();
}
}


  4.4 运行结果

red:255,0,0


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: