设置模式之-------原型模型

原型模型

原型模型的定义

用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。

原型模式的使用场景

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

原型模型的 UML 类图

在这里插入图片描述

角色介绍:

  • Client:客户端用户
  • Prototype: 抽象类或者接口,声明具备clone 能力
  • ConcretePrototype: 具体的原型类。

原型模型的简单实现

下面用简单的文档拷贝为例演示一下简单的原型模式,当我们修改文档时,一般会将当前文档拷贝一份,然后在文档副本上进行修改,这个就是我们这个案例的基础。

/*
* 文档类型,扮演的是 ConcretePrototype 角色,而 cloneable是代表 protorype角色
* */
public class WordDocument implements Cloneable{
    // 文本
    private String mText;
    // 图片名列表
    private ArrayList<String> mImages =  new ArrayList<String>();

    public WordDocument(){
        System.out.println("------------ WordDocument 构造函数——------");
    }

    protected WordDocument clone(){
        try{
            WordDocument document =(WordDocument) super.clone();
            document.mText = this.mText;
            document.mImages = this.mImages;
            return document;
        } catch (CloneNotSupportedException e) {
        }
        return null;
    }

    public String getmText(){
        return mText;
    }

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

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

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

    /*
    * 打印文档内容
    * */
    public void showDocument(){
        System.out.println("------------ Word content start ——------");
        System.out.println("text: "+ mText);
        System.out.println("Images List:");
        for (String imgName : mImages){
            System.out.println("iamge name : "+ imgName);
        }
        System.out.println("------------ Word content end——------");
    }

}

通过 WordDocument 类模拟了 word 文档中的基本元素,即图片和文字。 WordDocument 中的clone 方法用以实现对象克隆。

public class Client {
    public static void main(String[] args) {
        // 构建文档对象
        WordDocument document = new WordDocument();
        // 编辑文档,添加图片等
        document.setmText("这是一篇文档");
        document.addImage("图片1");
        document.addImage("图片2");
        document.addImage("图片3");
        document.showDocument();

        // 以原始文档为原型,拷贝一份副本
        WordDocument document1 = document.clone();
        document1.showDocument();

        // 修改文档副本,不会影响原始文档
        document1.setmText("这是修改的doc2文本");
        document1.showDocument();

        document.showDocument();

    }
}

运行结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L6TjGouh-1664930332652)(设计模式解析.assets/image-20220709101742205.png)]

浅拷贝和深拷贝

上面的原型拷贝实际上只是一个浅拷贝,这并不是将原始文档的所有字段都重新构造了一遍,而是副本文档的字段引用了原始文档的字段。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WtPoexoi-1664930332655)(设计模式解析.assets/image-20220709102243961.png)]

将main 函数的内容修改一下:

public static void main(String[] args) {
        // 构建文档对象
        WordDocument document = new WordDocument();
        // 编辑文档,添加图片等
        document.setmText("这是一篇文档");
        document.addImage("图片1");
        document.addImage("图片2");
        document.addImage("图片3");
        document.showDocument();

        // 以原始文档为原型,拷贝一份副本
        WordDocument document1 = document.clone();
        document1.showDocument();

        // 修改文档副本,不会影响原始文档
        document1.setmText("这是修改的doc2文本");
        document1.addImage("哈哈.jpg");
        document1.showDocument();

        document.showDocument();
    }

运行结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-quDRLsjn-1664930332656)(设计模式解析.assets/image-20220709103832887.png)]

从上面的运行结果,我们可以发现,最后两个文档的输出信息是一致的,这是因为备份文档只是引用原文档的地址,当备份文档增加一个图片时,原文档也会收到影响。这就是浅拷贝对象,如何解决这个问题呢,使用下面的代码实现深拷贝, clone 方法修改如下:

protected WordDocument clone(){
    try{
        WordDocument document =(WordDocument) super.clone();
        document.mText = this.mText;
        // 对 mImages 对象也调用 clone() 函数,进行深拷贝
        document.mImages = (ArrayList<String>) this.mImages.clone();
        return document;
    } catch (CloneNotSupportedException e) {
    }
    return null;
}

原型模型的核心问题就是对原始对象进行拷贝,这个模式的使用过程中需要注意的就是:深、浅拷贝的问题,建议在使用该模式时尽量使用深拷贝,避免操作副本时影响原始对象的问题。

原型模型优缺点

优点:

原型模型是内存中二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模型可以更好地体现其优点。

缺点:

这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的,实际开发当中应该注意这个潜在的问题,优点就是减少了约束,缺点也是减少了约束,需要大家在实际开发时考虑。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zpeien

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值