二哈谈设计模式之原型模式

原型模式



前言

  • 通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。就是java中的克隆技术,以某个对象为原型,复制出新的对象。显然,新的对象具备原型对象的特点。

  • 优势有:效率高(直接克隆,避免了重新执行构造过程步骤) 。

  • 克隆类似于new,但是不同于new。new创建新的对象属性采用的是默认值。克隆出的对象的属性值完全和原型对象相同。并且克隆出的新对象改变不会影响原型对象。然后,再修改克隆对象的值。

  • 原型模式实现:
    – Cloneable接口和clone方法
    – Prototype模式中实现起来最困难的地方就是内存复制操作,所幸在Java中提供了clone()方法替我们做了绝大部分事情。


一、浅拷贝与深拷贝

1.浅拷贝

/**
 * 浅拷贝
 */
public class Thing implements Cloneable{
    //定义一个私有变量
    private ArrayList<String> arrayList = new ArrayList<>();

    //加入数组
    public void setValue(String value){
        arrayList.add(value);
    }

    public ArrayList<String> getList(){
        return this.arrayList;
    }

    @Override
    protected Thing clone() {
        Thing thing = null;
        try {
            thing = (Thing) super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return thing;
    }
}
public class Client {
    public static void main(String[] args) {
        Thing thing = new Thing();
        thing.setValue("张三");

        Thing clone = thing.clone();
        clone.setValue("李四");

        System.out.println(thing.getList());
    }
}

结果为:
[张三, 李四]

原因:
浅拷贝只是拷贝对象本身,其对象内部的数组、引用对象都不拷贝,还是指向原生对象的内部元素地址。上例所示,两个对象共享了一个私有变量,在现实开发中很少用到,很不安全。

2.深拷贝

/**
 * 深拷贝
 */
public class Thing2 implements Cloneable{
    //定义一个私有变量
    private ArrayList<String> arrayList = new ArrayList<>();

    //加入数组
    public void setValue(String value){
        arrayList.add(value);
    }

    public ArrayList<String> getList(){
        return this.arrayList;
    }

    @Override
    protected Thing2 clone() {
        Thing2 thing = null;
        try {
            thing = (Thing2) super.clone();
            thing.arrayList = (ArrayList<String>) this.arrayList.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return thing;
    }
}

public class Client {
    public static void main(String[] args) {
        Thing2 thing = new Thing2();
        thing.setValue("张三");

        Thing2 clone = thing.clone();
        clone.setValue("李四");

        System.out.println(thing.getList());
    }
}

结果:
[张三]

原因:
在拷贝对象的同时,拷贝其引用的对象或数组,即可实现深拷贝。深拷贝的两个对象之间没有任何的关系,相互互不影响。

二、序列化实现拷贝

/**
 * 附件类
 */
public class Attachment implements Serializable {

    //附件名
    private String name;

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

    public String getName() {
        return name;
    }

    //执行下载操作
    public void download(){
        System.out.println("下载附件,文件名为"+name);
    }
}
public class Cilent2 {
    public static void main(String[] args) {
        MonthlyLog log_previous , log_new = null;
        log_previous = new MonthlyLog();
        Attachment attachment = new Attachment();
        log_previous.setAttachment(attachment);
        try {
            log_new = log_previous.deepClone();
        } catch (Exception e) {
            System.out.println("拷贝失败");
        }
        System.out.println("月报是否相同?"+(log_previous == log_new));
        System.out.println("附件是否相同?"+(log_previous.getAttachment() == log_new.getAttachment()));
    }
}

结果:
月报是否相同?false
附件是否相同?false

应用场景

– 原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone
的方法创建一个对象,然后由工厂方法提供给调用者。
– spring中bean的创建实际就是两种:单例模式和原型模式。(当然,原型
模式需要和工厂模式搭配起来)

总结

  • 优点:性能优良、逃避构造函数的约束(Object类的clone方法原理是从内存中以二进制流的方式进行拷贝,重新分配一个内存块。所以不会执行构造函数)
  • 使用场景:资源优化场景、性能和安全要求的场景、一个对象多个修改者的场景
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值