GOF23 设计模式之原型模式

什么是原型模式

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用

使用场景

(1)类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等,通过原型拷贝避免这些消耗。
(2)通过new一个对象需要非常繁琐的数据准备或访问权限,可以使用原型模式。
(3)一个对象需要提供给其他对象访问,而且各个调用者可能需要修改其值,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝

如何解决:利用已有的一个原型对象,快速地生成和原型对象一样的实例。

实现方式

  1. 实现Cloneable接口
  2. 重写Clone方法(super.clone)

实现代码

可以看到原型模式的实现非常简单,如下

public class Test implements Cloneable{

    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}

相关拓展

但是Object.clone()方法有在某些场景下些问题,先看下下面的问题吧?

问题1:

  1. 什么是浅拷贝?什么是深拷贝?浅拷贝与深拷贝有什么区别?

浅复制造成的现象:有个Test 对象继承Cloneable接口并重写clone()f方法并且还有两个属性 int id; User user; id是基本类型,user是一个对象。
如果这时Test t1 = new Test(1,user); Test t2 = t1.clone(); 这时会获取到t1,t2两个内容一样的对象,即t1.id 等于 t2.id, t1.user 等于 t2.user;问题就出在user上,我们都知道java中基本类型是值传递,而对象传的是引用,内存地址。如果我们修改t1中user的某个属性,那么t2中的那个属性的也会随t1的修改而改变。出现这样的拷贝叫浅拷贝,不会产生这样的叫深拷贝。

2、浅拷贝有哪些实现方式

  • 构造器
	public User(User u){
        this.id = u.id;
        this.name = u.name;
        //...其他属性
    }
  • Cloneable
public class User implements Cloneable{
    
    public int age;
    public String name; //String 也是对象,但不会像其他对象,因为String的值都是常量,即每次都是new 的一个新对象

    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}

3 、深拷贝有哪些实现方式

  • 构造器
  public class User implements Cloneable{
    
    public User(int age, String name){
        return new User(age, name);//直接重new一个User对象
    }

    public int age;
    public String name;

    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}
  • Cloneable
    就是User对象内部的对象属性必须全部实现了Cloneable接口
  public class User implements Cloneable{
  
    public int age;
    public ArrayList<String> nameList;//可能有多个别名

    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值