美文网首页设计模式
设计模式之原型模式 PrototypePattern

设计模式之原型模式 PrototypePattern

作者: sssssss_ | 来源:发表于2020-01-28 01:40 被阅读0次

    一、模式定义

    通过复制现有实例来创建新的实例,无需知道相应类的信息。

    二、模式使用场景

    • 类初始化需要消耗非常多的资源。
    • 通过new产生一个对象需要非常繁琐的数据准备或访问权限。
    • 提供给其他对象访问,而且各个调用者可能需要修改其值时。

    三、代码实现

    public class WordDocument implements Cloneable {
        private String mText;
        private ArrayList<String> mImages = new ArrayList<>();
        public WordDocument() {
        }
        @Override
        public WordDocument clone() {
            try {
                WordDocument doc = (WordDocument) super.clone();
                // 浅拷贝,只是单纯的只想了内存引用
                doc.mText = this.mText;
                doc.mImages = this.mImages;
                // 深拷贝,操作副本时不会影响原始对象
                doc.mImages = (ArrayList<String>) this.mImages.clone();
                return doc;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        //省略构造函数...
    }
    

    四、深拷贝和浅拷贝的区别

    • 深拷贝:拷贝时创建一个新的对象,并且所有属性都是新对象(指向新的内存地址)。对复制后的对象进行修改,不会影响原来对象的值。
    • 浅拷贝:拷贝时创建一个新的对象,对象中的属性如果是基本数据类型会新创建的对象,但是属性是引用类型不会创建新的对象,而是使用与之前的对象指向同一个内存地址。对复制后的对象进行修改,仍然会影响原来对象的值。

    五、Android源码分析

    Android中的Intent就实现了Cloneable接口,但是clone()方法中却是通过new来创建对象的。

    public class Intent implements Parcelable, Cloneable {
            //其他代码略
            @Override
            public Object clone() {
                //这里没有调用super.clone()来实现拷贝,而是直接通过new来创建
                return new Intent(this);
            }
            public Intent(Intent o) {
                this.mAction = o.mAction;
                this.mData = o.mData;
                this.mType = o.mType;
                this.mPackage = o.mPackage;
                this.mComponent = o.mComponent;
                this.mFlags = o.mFlags;
                this.mContentUserHint = o.mContentUserHint;
                if (o.mCategories != null) {
                    this.mCategories = new ArraySet<String>(o.mCategories);
                }
                if (o.mExtras != null) {
                    this.mExtras = new Bundle(o.mExtras);
                }
                if (o.mSourceBounds != null) {
                    this.mSourceBounds = new Rect(o.mSourceBounds);
                }
                if (o.mSelector != null) {
                    this.mSelector = new Intent(o.mSelector);
                }
                if (o.mClipData != null) {
                    this.mClipData = new ClipData(o.mClipData);
                }
            }
        }
    

    在《 Android 源码设计模式解析与实战》中讲到,在 Intent 的 clone 方法中并没有调用 super.clone() 方法来实现对象拷贝,而是调用 new Intent() 的原因是:使用 clone 和 new 需要根据构造对象的成本来决定,如果对象的构造成本或者构造较为麻烦的时候使用 clone 函数效率较高,否则可以使用 new 的形式。

    六、模式优缺点

    • 优点

      1. 原型模式是在内存中二进制流的拷贝,要比直接new一个对象性能好,特别是产生大量对象时。
      2. 隐藏制造新实例的重要性。
      3. 在重复创建相似对象的时候可以用。
    • 缺点

      1. 直接在内存中拷贝,构造函数是不会执行的,应该注意这个潜在问题。
      2. 每个类都必须配备一个克隆方法。
      3. 深拷贝会较为复杂。

    七、总结

    原型模式本质上就是对象拷贝,使用原型模式可以解决构造复杂对象的资源消耗问题,能够在某些场景下提升创建对象的效率。还有一个重要用途就是保护性拷贝,也就是某个对象对外可能是只读的,为了防止外部对这个只读对象进行修改,通常可以通过返回一个对象拷贝的形式实现只读的限制。另外需要区别浅拷贝和深拷贝,它们之间容易出现问题,

    相关文章

      网友评论

        本文标题:设计模式之原型模式 PrototypePattern

        本文链接:https://www.haomeiwen.com/subject/plluthtx.html