Java设计模式之原型设计模式

原型设计模式

一、举个小栗子

举个栗子:
现在有一个对象,如果我们需要对创建多个与该对象属性一致的对象,不能是使用 = 直接进行赋值的。

在创建新的对象的时候,总是要重新获取原始对象的属性,设置到新建的对象中,在创建的对象比较复杂的情况下,效率是比较低

例如:

public class Example{
	public static void main(String[] args){
		User originUser = new User(1,"kuyin");
		// 下面是对象复制功能,
		User copyUser = new User();
		copyUser.setId(originUser.getId());
		copyUser.setName(originUser.getName());
	}
}

class User{
	private int id;
	private String name;
	
	public User (){}
	public User(int id, String name){
		this.id = id ;
		this.name =name;
	}
	// 省略setter 和 getter 方法
}

从上面的栗子中,可以看到通过getXxx()获取到原有的值,然后使用setXxx()设置到新建的对象,一旦创建多个对象的时候,这是一个重复且无聊的动作。

所以就会会进行优化改进,这个时候就是原型设计模式出场的时候了。

二、原型模式的相关概念

1、原型模式(Prototype)

  • 用原型时指定创建对象的种类,并通过拷贝这些原型,创建新的对象。
  • 是一种创建型的设计模式,允许对象在创建一个可定制的对象,无需知道如何创建的细节。

2、实现思路一:利用Object的clone()方法(浅拷贝的方式)

利用java.lang.Object方法里就提供了克隆方法clone(),但是在使用clone()方法进行复制还是有下面的限制的:

  1. 要实现克隆,必须实现java.lang.Cloneable接口,否则在运行时调用clone()方法,会抛出CloneNotSupportedException异常。
  2. 返回的是Object类型的对象,所以使用时可能需要强制类型转换。
  3. .该方法是protected的,如果想让外部对象使用它,必须在子类重写该方法,设定其访问范围是public的,参见PackageInfo的clone()方法。
  4. Object类clone()方法的复制是采用逐字节的方式从内存复制数据,复制了属性的引用,而属性所指向的对象本身没有被复制,因此所复制的引用指向了相同的对象。由此可见,用这种方式复制对象是浅拷贝,不是深拷贝。

关于浅拷贝和深拷贝相关知识的可以查看该文章:
Java基础:浅复制、深复制、克隆接口Clone以及clone()方法

原型模式对于复杂的对象,往往需要进行深拷贝的。

3、深拷贝的实现方式两种实现方式

1、重写clone()方法来实现深拷贝。

2、通过对象序列化和反序列化来实现深拷贝(推荐

三、通过对象序列化和反序列化来实现深拷贝(推荐)

1、一言不合就是上代码

package design.model.prototype;

import java.io.*;

public class DeepConyBean implements Serializable {
    private Integer id;
    private OtherBean other;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public OtherBean getOther() {
        return other;
    }

    public void setOther(OtherBean other) {
        this.other = other;
    }

    @Override
    public String toString() {
        return "DeepConyBean{" +
                "id=" + id +
                ", other=" + other +
                '}';
    }

    public DeepConyBean deepCony(){
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos= new ObjectOutputStream(bos);
            oos.writeObject(this);
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            DeepConyBean copyBean = (DeepConyBean)ois.readObject();
            return copyBean;
        }catch (IOException exception){
            exception.printStackTrace();
        }catch ( ClassNotFoundException exception){
            exception.printStackTrace();
        }
        return null;
    }
}

class OtherBean implements Serializable{
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "OtherBean{" +
                "name='" + name + '\'' +
                '}';
    }
}

2、行不行,试试就只知道

测试代码

package design.model.prototype;

public class DeepCopyTest{
	public static void main(String[] args) {
        // 创建原型
        DeepConyBean origin = new DeepConyBean();
        origin.setId(1);
        OtherBean otherBean = new OtherBean();
        otherBean.setName("origin");
        origin.setOther(otherBean);

        // 执行深度复制
        DeepConyBean copy = origin.deepCony();
        System.out.println("---------通过==判断引用地址是否相同---------");
        System.out.println("origin == copy?" +(origin == copy));
        System.out.println("origin.other == copy.other?" +(origin.getOther() == copy.getOther()));
        System.out.println("---------查看数据---------");
        System.out.println("origin:"+origin);
        System.out.println("copy:"+copy);
        // 修改copy
        copy.setId(2);
        copy.getOther().setName("copy");
        System.out.println("---------修改后---------");
        System.out.println("origin:"+origin);
        System.out.println("copy:"+copy);
    }
} 

3、深度拷贝的结果

执行结果及分析

  • 对象引用的地址不想同,成员变量指向的地址也不想同。
  • 对复制后的copy对象进行修改,不会影响origin对象的值。
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值