设计模式之原型模式

1.原型模式

  原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。当创建给定类的实例的过程很昂贵或很复杂时,就使用原型模式。
  原型模式就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。

2.浅复制和深复制

  所谓的“浅复制”,即是被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象;对于“深复制”,则把引用对象的变量指向复制过的新对象,而不是原有的被引用对象。详见浅复制和深复制的解析
  浅复制与深复制的区别:对象的引用是否仍然指向原来的对象。

3.原型模式的结构

结构图
客户(Client)角色:客户类提出创建对象的请求。

抽象原型(Prototype)角色:这是一个抽象角色,通常由一个Java接口或Java抽象类实现。此角色给出所有的具体原型类所需的接口。

具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。


Prototype类,抽象原型

public interface Prototype{
    /**
     * 克隆自身的方法
     * @return 一个从自身克隆出来的对象
     */
    public Object clone();
}

ConcretePrototype类,具体原型类

public class ConcretePrototype implements Prototype {
    //简易克隆,新建一个克隆对象
    public Object clone(){
        Prototype prototype = new ConcretePrototype();
        return prototype;
    }

}

使用Java的clone()方法实现对象的克隆,需实现Cloneable接口,Cloneable是标识接口,可不实现重写。

public class ConcretePrototype2 implements Cloneable {
    //若要重写clone方法
    public Object clone() throws CloneNotSupportedException{
        return super.clone();
    }

}

注意:当克隆对象包含着对其他对象的引用时,需要重写其对象的clone()方法

4.clone()和序列化

I. clone()

示例为直线对象,直线上有左右两个点对象的引用


点对象

public class Node implements Cloneable {
    private boolean flag; 
    private int Xpos;
    private int Ypos;
    private int grade;   //顶点的值

    public Node(){}  //无参构造函数

    //setter和getter及其他方法

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();  
    }
}

线对象

public class Line implements Cloneable {
    private boolean flag; 
    private Node Lnode;
    private Node Rnode;
    private char operator;   //运算符

    public Line(){}

    //setter和getter及其他方法

    @Override
    protected Object clone() throws CloneNotSupportedException { 
        Line line =  (Line) super.clone();
        //对引用的对象也进行复制 
        line.Lnode = (Node) Lnode.clone();
        line.Rnode = (Node) Rnode.clone();
        return line;
    }
}

II. 序列化及反序列化

为实现序列化,所有需要复制的对象都需要实现java.io.Serializable接口。

    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();
    }

对容器的序列化(容器内对象需实现Serializable)

    public ArrayList deepCopy(ArrayList src) throws IOException, ClassNotFoundException{
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteOut);
        out.writeObject(src);
        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
        ObjectInputStream in =new ObjectInputStream(byteIn);
        ArrayList dest = (ArrayList)in.readObject();
        return dest;
    }

5.总结

  I. 一般在初始化的信息不发生变化的情况下,克隆是最好的办法。这既隐藏了对象创建的细节,又对性能有所提高。
  II. 不需重新初始化对象,而是动态地获得对象运行时的状态。
  III. 向客户隐藏制造新示例的复杂性。



参考资料:
1.《Head Frist设计模式》
2.《大话设计模式》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值