重学设计模式之原型设计模式

102 阅读1分钟

目录

  • 原型设计模式介绍
  • 原型设计模式使用场景
  • 原型设计模式代码实现
  • 浅拷贝和深拷贝

原型设计模式介绍

原型设计模式指的是,用原型实例指定了创建对象的种类,并且通过拷贝原型的方式来创建新的对象。

原型模式的使用场景

  1. 类的初始化需要消耗非常多资源(数据、硬件等资源),通过原型复制可以避免类似等消耗。
  2. 同过 new 产生一个对象需要非常繁琐等数据准备或访问权限。
  3. 一个对象需要提供给其它对象访问,且各个访问对象可能都需要修改其值,可以使用原型设计模式实现保护性拷贝。

原型设计模式等代码实现

使用 Cloneable 实现拷贝时,需要注意构造函数不会执行。

  • 首先是原型对象等构建
public class Notebook implements Cloneable {

    /**
     * 作者
     */
    private String author;
    /**
     * content
     */
    private List<String> articles = new ArrayList<>();

    public Notebook() {
        System.out.println("====================    Notebook 构造函数    ====================");
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public void addArticle(String article) {
        articles.add(article);
    }

    @NonNull
    @Override
    protected Notebook clone() {
        try {
            Notebook notebook = (Notebook) super.clone();
            notebook.author = this.author;
            notebook.articles = this.articles;
            return notebook;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public void printContent() {
        System.out.println("====================    Notebook print start    ====================");
        System.out.println("author = " + author);
        System.out.println("articles = ");
        for (String article : articles) {
            System.out.println("    article = " + article);
        }
        System.out.println("====================    Notebook print end      ====================");
    }
}
  • 访问对象对原型对访问
public class ExampleUnitTest {
    @Test
    public void notebookTest() {
        // 创建笔记本并添加部分内容
        Notebook notebook = new Notebook();
        notebook.setAuthor("刘备");
        notebook.addArticle("三国演义");
        notebook.addArticle("水浒传");
        notebook.addArticle("西游记");
        System.out.println("原型笔记数据 =    ");
        notebook.printContent();

        System.out.println("拷贝后副本笔记数据 =    ");
        Notebook cloneNotebook = notebook.clone();
        cloneNotebook.printContent();

        // 修改内容
        cloneNotebook.setAuthor("刘备v2");
        cloneNotebook.addArticle("红楼梦");
        System.out.println("修改后的副本笔记数据 =    ");
        cloneNotebook.printContent();

        // 原始笔记本内容
        System.out.println("副本笔记数据 =    ");
        notebook.printContent();
    }
}

====================    Notebook 构造函数    ====================
原型笔记数据 =    
====================    Notebook print start    ====================
author = 刘备
articles = 
    article = 三国演义
    article = 水浒传
    article = 西游记
====================    Notebook print end      ====================
副本笔记数据 =    
====================    Notebook print start    ====================
author = 刘备
articles = 
    article = 三国演义
    article = 水浒传
    article = 西游记
====================    Notebook print end      ====================
修改后的副本笔记数据 =    
====================    Notebook print start    ====================
author = 刘备v2
articles = 
    article = 三国演义
    article = 水浒传
    article = 西游记
    article = 红楼梦
====================    Notebook print end      ====================
原始笔记数据 =    
====================    Notebook print start    ====================
author = 刘备
articles = 
    article = 三国演义
    article = 水浒传
    article = 西游记
    article = 红楼梦
====================    Notebook print end      ====================

浅拷贝和深拷贝

  • 以上的原型设计模式实现方式中的拷贝实际上并不是将原始笔记的所有字段都重新构造一份,而是副本笔记的字段引用原始笔记的字段。所以修改副本笔记中 articles 数据后原始笔记内容也改变了。
  • 解决方式就是使用深拷贝,将原型的字段逐一拷贝一次。
public class Notebook implements Cloneable {

    /**
     * 作者
     */
    private String author;
    /**
     * content
     */
    private ArrayList<String> articles = new ArrayList<>();

    public Notebook() {
        System.out.println("====================    Notebook 构造函数    ====================");
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public void addArticle(String article) {
        articles.add(article);
    }

    @NonNull
    @Override
    protected Notebook clone() {
        try {
            Notebook notebook = (Notebook) super.clone();
            notebook.author = this.author;
            notebook.articles = (ArrayList<String>) this.articles.clone();
            return notebook;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public void printContent() {
        System.out.println("====================    Notebook print start    ====================");
        System.out.println("author = " + author);
        System.out.println("articles = ");
        for (String article : articles) {
            System.out.println("    article = " + article);
        }
        System.out.println("====================    Notebook print end      ====================");
    }
}