Java设计模式4-原型模式

原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的.
说白了就是一个类实现了Cloneable,重写clone方法,就可以调用这个类的对象复制实例了。

1、拷贝分类
这里写图片描述
原型模式中的拷贝分为”浅拷贝”和”深拷贝”:
浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.
深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制.

2、浅拷贝演示1

a.定义一个Prototype类
        public class Prototype implements Cloneable {
            private String name;

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }

            public Object clone() {
                try {
                    return super.clone();
                } catch (CloneNotSupportedException e) {   
                    e.printStackTrace();
                    return null;
                }
            } 
        }
b.使用
        public class TestMain {
            public static void main(String[] args) {
                testPrototype();
            }

            private static void testPrototype(){
                Prototype pro = new Prototype();
                pro.setName("original object");
                Prototype pro1 = (Prototype)pro.clone();
                pro.setName("changed object");

                System.out.println("original object:" + pro.getName());
                System.out.println("cloned object:" + pro1.getName());

            }
        }
        结果:
        original object:changed object
        cloned object:original object

3、浅拷贝演示2

我们定义一个Prototype类,不去实现Cloneable接口,看看这个类里面的属性能不能被复制(答案是不能的)

a.我们定义一个Prototype类,不去实现Cloneable接口
        public class Prototype{
            private String name;
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            } 
        }
b.定义一个NewPrototype,实现Cloneable接口
        public class NewPrototype implements Cloneable {
            private String id;
            public String getId() {
                return id;
            }
            public void setId(String id) {
                this.id = id;
            }

            //将上面的类作为这个类的一个属性,看看能不能clone
            private Prototype prototype;
            public Prototype getPrototype() {
                return prototype;
            }
            public void setPrototype(Prototype prototype) {
                this.prototype = prototype;
            }

            public Object clone(){ 
                try {
                    return super.clone();
                } catch (CloneNotSupportedException e) {
                    e.printStackTrace();
                    return null;
                }  
            }
        }
c.测试使用
        public class TestMain {

            public static void main(String[] args) {
                testPrototype();
            }

            private static void testPrototype(){
                Prototype pro = new Prototype();
                pro.setName("original object");
                NewPrototype newObj = new NewPrototype();
                newObj.setId("test1");
                newObj.setPrototype(pro);

                NewPrototype copyObj = (NewPrototype)newObj.clone();
                copyObj.setId("testCopy");
                //这个copyObj对象里面的属性prototype是没有复制的,指向的是同一个对象
                copyObj.getPrototype().setName("changed object");

                System.out.println("original object id:" + newObj.getId());
                System.out.println("original object name:" + newObj.getPrototype().getName());

                System.out.println("cloned object id:" + copyObj.getId());
                System.out.println("cloned object name:" + copyObj.getPrototype().getName());

            }

        }

        结果:
        original object id:test1
        original object name:changed object //已经改变了原来的值了
        cloned object id:testCopy
        cloned object name:changed object
可以看出来,不实现Cloneable的类属性是不能被复制的。如果要prototype这个属性也被复制,只要Prototype这个类实现Clonbeable接口就行。

4、深拷贝

利用串行化来做深复制
把对象写道流里的过程是串行化(Serilization)过程;
把对象从流中读出来是并行化(Deserialization)过程. 写在流里的是对象的一个拷贝,然后再从流里读出来重建对象.

a.创建一个PrototypeSe类,实现Serializable序列化接口
        public class PrototypeSe implements Serializable {

            private String name;

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }

        }
b.创建一个NewPrototypeSe,同样实现Serializable接口
        public class NewPrototypeSe implements Serializable {

            private String id;
            public String getId() {
                return id;
            }
            public void setId(String id) {
                this.id = id;
            }

            private PrototypeSe prototype;
            public PrototypeSe getPrototype() {
            return prototype;
            }
            public void setPrototype(PrototypeSe prototype) {
                this.prototype = prototype;
            }

            public Object deepClone(){
                try {
                    ByteArrayOutputStream bo = new ByteArrayOutputStream();
                    ObjectOutputStream oo = new ObjectOutputStream(bo);   
                    oo.writeObject(this);   

                    ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
                    ObjectInputStream oi = new ObjectInputStream(bi);
                    return oi.readObject(); 
                } catch (IOException | ClassNotFoundException e) {
                    e.printStackTrace();
                    return null;
                }
            }
        }   
c.使用
        public class TestDeepClone {
            public static void main(String[] args) {
                PrototypeSe po = new PrototypeSe();
                po.setName("test1");
                NewPrototypeSe se = new NewPrototypeSe();
                se.setPrototype(po);

                NewPrototypeSe deepClone = (NewPrototypeSe)se.deepClone();
                deepClone.getPrototype().setName("test2");

                System.out.println("original name:" + se.getPrototype().getName());
                System.out.println("cloned name:" + deepClone.getPrototype().getName());
            }
        }
        结果:
        original name:test1
        cloned name:test2
注意:原型类并没有实现Cloneable接口,而是自己定义一个deepClone方法复制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值