设计模式--原型模式

原型模式与深拷贝、浅拷贝

基本概念

使用一个已经创建的对象作为原型,通过复制该对象来创建一个新的该类型的对象。Java自带原型模式,通过实现Cloneable接口实现,这种创建对象的方式比new对象的效率更高。

原型模式通常用来保存对象某一过程中的状态,以实现在必要的时候撤销对对象的更改。

此方法的缺陷:

  1. 每一个类都需要实现clone()方法,而clone()方法位于类内部,当需要对类代码进行修改时,此方法也需要修改。
  2. 当需要深克隆时,此类中的每一个引用类型对象都需要支持深克隆,实现较麻烦。

模式的实现

  1. 创建原型类,实现Cloneable接口,并重写clone()方法

    原型类的引用类型属性

    public class Member implements Cloneable{
        private int age;
        private String name;
        private double length;
    
        public Member(int age, String name, double length) {
            this.age = age;
            this.name = name;
            this.length = length;
        }
    
        @Override
        protected Member clone() throws CloneNotSupportedException {
            Member res = (Member) super.clone();
            return res;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public double getLength() {
            return length;
        }
    
        public void setLength(double length) {
            this.length = length;
        }
    }
    

    原型类

    public class Collection implements Cloneable {
        private Member member;
        private int id;
    
        public Collection(Member member, int id) {
            this.member = member;
            this.id = id;
        }
    
        @Override
        protected Collection clone() throws CloneNotSupportedException {
            Collection res = (Collection) super.clone();
            //res.setMember(this.getMember().clone());
            return res;
        }
    
        public Member getMember() {
            return member;
        }
    
        public void setMember(Member member) {
            this.member = member;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    }
    
  2. 使用该类的clone()方法实现克隆

    public class ProtoDemo {
        public static void main(String[] args) throws CloneNotSupportedException {
            Member zhangf = new Member(12, "张飞", 12.33);
            Collection coll = new Collection(zhangf, 1);
            Collection coll2 = (Collection) coll.clone();
    
            String str1="collect01\tid="+coll.getId()+"\t"+coll.getMember()+"\tmem="+coll;
            String str2="collect02\tid="+coll2.getId()+"\t"+coll2.getMember()+"\tmem="+coll2;
    
            System.out.println(str1);
            System.out.println(str2);
          
            System.out.println("=============");
            coll.getMember().setName("刘备");
            System.out.println("coll1`s name is "+coll.getMember().getName());
            System.out.println("coll2`s name is "+coll2.getMember().getName());
        }
    }
    

以上代码实现类浅拷贝,打印结果如下:

collect01	id=1	cn.sunyog.prototype.Member@e73f9ac	mem=cn.sunyog.prototype.Collection@61064425
collect02	id=1	cn.sunyog.prototype.Member@e73f9ac	mem=cn.sunyog.prototype.Collection@7b1d7fff
=============
coll1`s name is 刘备
coll2`s name is 刘备

可以看出,当修改了coll对象中membername属性时,coll2对象中对应的次属性也跟着被修改了。如需要实现两个对象互不影响,需要实现深拷贝,即重写Collection类的clone()方法,手动修改它的所有引用类型属性。代码如下:

@Override
protected Collection clone() throws CloneNotSupportedException {
    Collection res = (Collection) super.clone();
  	//深拷贝
    res.setMember(this.getMember().clone());
    return res;
}

以上代码修改后,打印结果如下:

collect01	id=1	cn.sunyog.prototype.Member@5e2de80c	mem=cn.sunyog.prototype.Collection@1d44bcfa
collect02	id=1	cn.sunyog.prototype.Member@266474c2	mem=cn.sunyog.prototype.Collection@6f94fa3e
=============
coll1`s name is 刘备
coll2`s name is 张飞

可见两个对象的name属性互不影响,实现了深拷贝

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李奇技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值