原型模式——文档复制

来源:互联网 发布:服务器与数据库的区别 编辑:程序博客网 时间:2024/05/20 11:26

文档是我们在计算机上记录文字等一个工具,通常一份文档有一个大标题,也有许多个副标题。文档的复制拷贝也很常见,那么怎么在程序设计中运用原型模式来模拟文档的复制呢?
首先,通过UML图大概了解一下原型模式吧:
这里写图片描述

Client:客户端类
Prototype:抽象类或接口,实现了Cloneable接口
ConcretePrototype:具体的原型类

既然需要模拟文档复制,那么就需要先建立一个文档:

//Docment相当于ConcretePrototype,而Cloneable接口相当于Prototypepublic class Document implements Cloneable{    //主标题    private String title;    //所有副标题    private ArrayList<String> subTitles = new ArrayList<>();    @Override    protected Document clone() throws CloneNotSupportedException {        Document mNewspaper = (Document) super.clone();        mNewspaper.title = title;        mNewspaper.subTitles = subTitles;        return mNewspaper;    }    //添加副标题    public void addSubTitle(String content) {        subTitles.add(content);    }    //设置主标题    public void setTitle(String title) {        this.title = title;    }    //文档内容    public String getDocText() {        return title + " " + subTitles.toString();    }}

然后需要一个客户端来进行复制:

public class Client {    public static void main(String[] args) throws CloneNotSupportedException {        Document doc = new Document();        doc.setTitle("标题");        doc.addSubTitle("副标题1");        doc.addSubTitle("副标题2");        doc.addSubTitle("副标题3");        System.out.println("原文档:" + doc.getDocText());        Document docCloning = doc.clone();        System.out.println("复制的文档:" + docCloning.getDocText());    }}

结果为:

原文档:标题 [副标题1, 副标题2, 副标题3]
复制的文档:标题 [副标题1, 副标题2, 副标题3]

这就是原型模式的实现,但是却会存在下列的问题,将代码修改一下:

public class Client {    public static void main(String[] args) throws CloneNotSupportedException {        Document doc = new Document();        doc.setTitle("标题");        doc.addSubTitle("副标题1");        doc.addSubTitle("副标题2");        doc.addSubTitle("副标题3");        System.out.println("原文档:" + doc.getDocText());        Document docCloning = doc.clone();        System.out.println("复制的文档:" + docCloning.getDocText());        System.out.println();        //克隆的对象添加一个副标题,之后输出克隆的和原来的DOC内容        docCloning.addSubTitle("副标题4");        System.out.println("复制的文档:" + docCloning.getDocText());        System.out.println("原文档:" + doc.getDocText());    }}

结果为:

原文档:标题 [副标题1, 副标题2, 副标题3]
复制的文档:标题 [副标题1, 副标题2, 副标题3]

复制的文档:标题 [副标题1, 副标题2, 副标题3, 副标题4]
原文档:标题 [副标题1, 副标题2, 副标题3, 副标题4]

会发现原来的文档的副标题也修改了,这就引出了克隆的知识点:浅克隆与深克隆。
上述的克隆方式即为浅克隆,虽然克隆出了一个新的文档,但是他们对于subTitles的引用还是指向了同一个对象。要想避免出现这种问题,则需要使用深克隆,方法也很简单:

@Override    protected Document clone() throws CloneNotSupportedException {        Document mNewspaper = (Document) super.clone();        mNewspaper.title = title;        //将引用的字段subTitles也进行克隆        mNewspaper.subTitles = (ArrayList<String>) subTitles.clone();        return mNewspaper;    }

结果为:

复制的文档:标题 [副标题1, 副标题2, 副标题3, 副标题4]
原文档:标题 [副标题1, 副标题2, 副标题3]

原型模式的应用相对简单,只不过需要注意到什么时候应该用浅克隆,或是深克隆。该模式适用于当需要一个相同的副本,要避免使用new来产生新对象导致资源消耗时使用。

原型模式的优缺点

  • 优点
    – 相对于用new产生一个对象来说,会消耗更少的资源,尤其是在循环体内。
  • 缺点
    -原型模式是克隆二进制流,并不会执行构造方法。
1 0
原创粉丝点击