原型模式实例笔记

以文档复制为例记录。

1. 具体原型 及原型角色

import android.util.Log;

import androidx.annotation.NonNull;

import java.util.ArrayList;
import java.util.List;

/**
 * 文档类型,扮演的是ConcretePrototype角色,而Cloneable 代表的是prototype 角色
 */
public class WordDocument implements Cloneable {
    //文本
    private String mText;
    //图片列表, 使用ArrayList 是因为它实现了Cloneable接口, 可以调用其clone()方法, 而接口List 则没有实现Cloneable
    private ArrayList<String> mImages = new ArrayList<String>();

    public WordDocument() {
        Log.d("WordDocument", "----------- WordDocument 构造函数");
    }

    @NonNull
    @Override
    public WordDocument clone() throws CloneNotSupportedException {
        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;
    }

    public String getText() {
        return mText;
    }

    public void setText(String mText) {
        this.mText = mText;
    }

    public List<String> getImages() {
        return mImages;
    }

    public void addImage(String image) {
        this.mImages.add(image);
    }

    public void showDocument(){
        Log.d("WordDocument", "----------- WordDocument content start");
        Log.d("WordDocument", "Text: " + mText);
        Log.d("WordDocument", "Image List: ");
        for(String imageName: mImages) {
            Log.d("WordDocument", "Image name: " + imageName);
        }

        Log.d("WordDocument", "----------- WordDocument content end");
    }
}

这里需要注意浅拷贝和深拷贝,

            //doc.mImages = this.mImages; //浅拷贝,复制的是引用,会修改原来的
            doc.mImages = (ArrayList<String>) this.mImages.clone();//深拷贝,对非基本类型进行深拷贝

其中,例如 Android 中的Bundle 对象,

如果 Bundle extra1 = new Bundle();

Bundle extra2 = extra1;

则表示 extra2 会使用和extra1一样的引用, 当同时操作 Bundle的成员变量 map 相关时,则会抛出异常 (ConcurrentModificationException  java.util.ConcurrentModificationException:)

解决方法是使用 clone 复制一份, 即 extra2 = extra1.clone() ; // 其实也是浅拷贝,不过它会创建新的map

/**
 * A mapping from String keys to various {@link Parcelable} values.
 *
 * @see PersistableBundle
 */
public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
    static {
        EMPTY = new Bundle();
        EMPTY.mMap = ArrayMap.EMPTY;


    /**
     * Clones the current Bundle. The internal map is cloned, but the keys and
     * values to which it refers are copied by reference.
     */
    @Override
    public Object clone() {
        return new Bundle(this);
    }

    /**
     * Make a deep copy of the given bundle.  Traverses into inner containers and copies
     * them as well, so they are not shared across bundles.  Will traverse in to
     * {@link Bundle}, {@link PersistableBundle}, {@link ArrayList}, and all types of
     * primitive arrays.  Other types of objects (such as Parcelable or Serializable)
     * are referenced as-is and not copied in any way.
     */
    public Bundle deepCopy() {
        Bundle b = new Bundle(false);
        b.copyInternal(this, true);
        return b;
    }

 

 

2. 测试代码

    @Test
    fun testPrototype() {
        Log.d(TAG, "====================Prototype====================")

        //1.构建文件对象
        val originDoc = WordDocument()
        //2.编辑文本及添加图片
        originDoc.text = "这是一篇文档"
        originDoc.addImage("图片1")
        originDoc.addImage("图片2")
        originDoc.addImage("图片3")
        originDoc.showDocument()

        //以原始文档为原型,拷贝一份副本
        val doc2 = originDoc.clone()
        // 修改文档副本,不会影响原来的文档
        doc2.text = "这是修改过的Doc2文本"
        doc2.showDocument()

        //确认原始文档
        originDoc.showDocument()
    }

3. 输出结果

17:20:25.386 D/DesignPattern: ====================Prototype====================
17:20:25.386 D/WordDocument: ----------- WordDocument 构造函数

17:20:25.386 D/WordDocument: ----------- WordDocument content start
17:20:25.386 D/WordDocument: Text: 这是一篇文档
17:20:25.386 D/WordDocument: Image List: 
17:20:25.387 D/WordDocument: Image name: 图片1
17:20:25.387 D/WordDocument: Image name: 图片2
17:20:25.387 D/WordDocument: Image name: 图片3
17:20:25.387 D/WordDocument: ----------- WordDocument content end

17:20:25.387 D/WordDocument: ----------- WordDocument content start
17:20:25.387 D/WordDocument: Text: 这是修改过的Doc2文本
17:20:25.387 D/WordDocument: Image List: 
17:20:25.387 D/WordDocument: Image name: 图片1
17:20:25.387 D/WordDocument: Image name: 图片2
17:20:25.387 D/WordDocument: Image name: 图片3
17:20:25.387 D/WordDocument: Image name: 新的图片.jpg
17:20:25.388 D/WordDocument: ----------- WordDocument content end

17:20:25.388 D/WordDocument: ----------- WordDocument content start
17:20:25.388 D/WordDocument: Text: 这是一篇文档
17:20:25.388 D/WordDocument: Image List: 
17:20:25.388 D/WordDocument: Image name: 图片1
17:20:25.388 D/WordDocument: Image name: 图片2
17:20:25.388 D/WordDocument: Image name: 图片3
17:20:25.388 D/WordDocument: ----------- WordDocument content end

由此看出, 复制的文档中, 添加了一张图片  ("新的图片.jpg"), 并不会影响原始的文档, 这是使用了深拷贝

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值