原型模式学习心得

原型模式就是通过复制现在已经存在的对象来创建一个新的对象。
原型模式一般包含两种角色
1.抽象原型类
2.具体原型类
java本身的object已经实现了原型模式,它提供了一个clone()方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,我们需要将clone方法的作用域修改为public类型。

另外java还提供了一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。


实现如下

此处抽象原型类为object类

具体原型类为ConcretePrototype类

public class ConcretePrototype implements Cloneable{
    private ConcretePrototypeMethod m1;
    private String m2;
    private int m3;

    public Object clone(){
        
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public ConcretePrototypeMethod getM1() {
        return m1;
    }

    public void setM1(ConcretePrototypeMethod m1) {
        this.m1 = m1;
    }

    public String getM2() {
        return m2;
    }

    public void setM2(String m2) {
        this.m2 = m2;
    }

    public int getM3() {
        return m3;
    }

    public void setM3(int m3) {
        this.m3 = m3;
    }
}


//为具体原型类提供一个对象属性
public class ConcretePrototypeMethod {

    private String m;
    
    public String getM() {
        return this.m;
    }

    public void setM(String m) {
        this.m = m;
    }
    

}

//测试代码

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ConcretePrototype prototype1 = new ConcretePrototype();
        
        
        ConcretePrototypeMethod m1 = new  ConcretePrototypeMethod();
        m1.setM("this is object1");
        prototype1.setM1(m1);
        prototype1.setM2("this is string1");
        prototype1.setM3(1);
        
        ConcretePrototype prototype2 = (ConcretePrototype) prototype1.clone();
        System.out.println(prototype2.getM1().getM());
        System.out.println(prototype2.getM2());
        System.out.println(prototype2.getM3());
        
        prototype1.getM1().setM("object1 is change");
        prototype1.setM2("string1 is change");
        prototype1.setM3(2);
        
        System.out.println(prototype2.getM1().getM());
        System.out.println(prototype2.getM2());
        System.out.println(prototype2.getM3());
    }

}

输出如下

this is object1
this is string1
1
object1 is change
this is string1
1


我们发现对于克隆出来的对象prototype2,如果改变源对象prototype1的属性m1,也会导致prototype2对象的属性发生变化。这是因为深拷贝和浅拷贝的原因。java的object的colne方法中只会对八种基本类型和String类型进行深拷贝,而不会对其他的类型进行深拷贝,也就是说,其他的如引用类型clone方法拷贝过去的也只是该对象的引用。这就导致了拷贝出来的对象和源对象都持有同一个引用,那么,只要由一个对象对这个引用代表的对象进行了操作,另一个对象也会受到其影响。那么我们有什么方法可以让引用对象也进行深拷贝呢,这里介绍一种方法。

将需要复制的对象放入流中,再将其取出

import java.io.Serializable;


public class ConcretePrototype implements Serializable{
    private ConcretePrototypeMethod m1;
    private String m2;
    private int m3;


    public ConcretePrototypeMethod getM1() {
        return m1;
    }

    public void setM1(ConcretePrototypeMethod m1) {
        this.m1 = m1;
    }

    public String getM2() {
        return m2;
    }

    public void setM2(String m2) {
        this.m2 = m2;
    }

    public int getM3() {
        return m3;
    }

    public void setM3(int m3) {
        this.m3 = m3;
    }
}


import java.io.Serializable;


public class ConcretePrototypeMethod  implements Serializable{

    private String m;
    
    public String getM() {
        return this.m;
    }

    public void setM(String m) {
        this.m = m;
    }
    
}


    import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;


public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ConcretePrototype prototype1 = new ConcretePrototype();
        
        
        ConcretePrototypeMethod m1 = new  ConcretePrototypeMethod();
        m1.setM("this is object1");
        prototype1.setM1(m1);
        prototype1.setM2("this is string1");
        prototype1.setM3(1);
        ConcretePrototype prototype2 = null;
        
        try
        {
            if (prototype1 != null)
            {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject(prototype1);
                oos.close();
                ByteArrayInputStream bais = new ByteArrayInputStream(baos
                        .toByteArray());
                ObjectInputStream ois = new ObjectInputStream(bais);
                prototype2 = (ConcretePrototype) ois.readObject();
                ois.close();
            }
        } catch (IOException e)
        {
            e.printStackTrace();
        } catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        
        
        
        System.out.println(prototype2.getM1().getM());
        System.out.println(prototype2.getM2());
        System.out.println(prototype2.getM3());
        
        prototype1.getM1().setM("object1 is change");
        prototype1.setM2("string1 is change");
        prototype1.setM3(2);
        
        System.out.println(prototype2.getM1().getM());
        System.out.println(prototype2.getM2());
        System.out.println(prototype2.getM3());
    }

}


输出结果

this is object1
this is string1
1
this is object1
this is string1
1

可以看出,两个对象所持有的引用都不一样,达到了深克隆的效果











转载于:https://my.oschina.net/kakakaka/blog/355173

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值