美文网首页
创建型-原型模式

创建型-原型模式

作者: iarchitect | 来源:发表于2018-10-09 21:06 被阅读0次

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

类型:创建型模式。

角色:
抽象原型类:它是声明克隆方法的接口,是所有具体原型类的公共父类,可以是接口,抽象类,甚至是具体实现类。
具体原型类:实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。
客户类:让一个原型对象克隆自身从而创建一个新的对象,在客户类中只需要直接实例化创建一个原型对象,在通过调用该对象的克隆方法即可得到多个相同的对象。

预备知识:
在Java中的数据类型分为基本数据类型(byte,short,int,long,float,double,char,boolean)和引用数据类型(类,接口类型,数组类型,枚举类型,注解类型) ,两者的区别是,基本数据类型在被创建时,在栈上给其划分出一块内存,将数值直接存储在栈上。引用数据类型在被创建时,首先要在栈上给其引用(句柄)分配一块内存,而对象的具体信息都存储在堆内存上,然后由栈上的引用指向堆中对象的地址。

下面以复制一本书为例:
浅拷贝原型模式代码示例:

public class Author {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

public class Book implements Cloneable {
    private String title;
    private int pageNum;
    private Author author;

    @Override
    public Book clone() {
        Book book = null;

        try {
            book = (Book) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        return book;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getPageNum() {
        return pageNum;
    }

    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }

    public Author getAuthor() {
        return author;
    }

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

public class Test {

    public static void main(String[] args) {
        Book book1 = new Book();
        Author author = new Author();
        author.setAge(30);
        author.setName("smart");
        book1.setAuthor(author);
        book1.setTitle("times");
        book1.setPageNum(300);

        Book book2 = book1.clone();

        System.out.println(book1 == book2);
        System.out.println(book1.getAuthor() == book2.getAuthor());
        System.out.println(book1.getTitle() == book2.getTitle());
        System.out.println(book1.getPageNum() == book2.getPageNum());
    }

}

运行结果:


image.png

分析:
根据输出结果我们可以发现,复制出来的对象,在堆上重新开辟了内存空间,对象中各属性保持相等,对于基本数据类型,很好理解,在栈上重新开辟空间,复制相应的zhi,但是对于引用数据类型,说明它们指向的对象是相同的,并没有重新开辟内存空间,即引用类型的属性所指向的对象,并没有复制。我们称其为浅复制或浅拷贝

深拷贝原型模式代码示例:

import java.io.Serializable;

public class AuthorS implements Serializable {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

import java.io.*;

public class BookS implements Serializable {
    private String title;
    private int pageNum;
    private AuthorS authorS;

    public BookS deepClone() throws IOException, ClassNotFoundException {
        //写入当前对象的二进制流
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(this);

        //读出二进制流产生的新对象
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);

        return (BookS) objectInputStream.readObject();
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getPageNum() {
        return pageNum;
    }

    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }

    public AuthorS getAuthorS() {
        return authorS;
    }

    public void setAuthorS(AuthorS authorS) {
        this.authorS = authorS;
    }
}

public class TestS {

    public static void main(String[] args) throws  Exception{
        BookS bookS1 = new BookS();
        AuthorS authorS = new AuthorS();
        authorS.setAge(30);
        authorS.setName("smart");
        bookS1.setAuthorS(authorS);
        bookS1.setTitle("times");
        bookS1.setPageNum(300);

        BookS bookS2 = bookS1.deepClone();

        System.out.println(bookS1 == bookS2);
        System.out.println(bookS1.getAuthorS() == bookS2.getAuthorS());
        System.out.println(bookS1.getTitle() == bookS2.getTitle());
        System.out.println(bookS1.getPageNum() == bookS2.getPageNum());
    }

}

运行结果:


image.png

分析:
深拷贝不仅在堆上开辟了空间以存储复制出来的对象,甚至连对象中的引用类型的属性所指向的对象也得以复制,重新开辟了堆空间存储。

总结:
优点:
1,当创建的新的对象实例比较复杂时,使用原型模式可以简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率。
2,提供了简化的创建结构
3,使用深拷贝的方式保存对象的状态,可辅助实现撤销操作。
缺点:
1,需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了“开闭原则”
2,在实现深拷贝时需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了实现深拷贝,每一层对象对应的类都必须支持深拷贝,实现起来可能会比较麻烦。

相关文章

  • 创建型设计模式——原型模式

    定义 原型模式是一个创建型的设计模式。用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。原型模式多用于...

  • Objective-C 原型模式 -- 简单介绍和使用

    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。Prototype原型模式是一种创建型设计模式,P...

  • 三、原型模式

    原型模式用于创建重复对象的同时保持性能,该模式属于创建型设计模式,是创建对象的最佳实现方式。 为什么要使用原型模式...

  • 设计模式最佳实践之原型模式

    What 原型模式:是一个创建型的模式。用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。 使用场景:...

  • 设计模式[4]-原型模式-Prototype Pattern

    1. 原型模式简介 原型模式(Prototype Pattern)是创建型设计模式,根据一个原型对象,通过Clon...

  • 原型模式

    个人博客http://www.milovetingting.cn 原型模式 模式介绍 原型模式是一个创建型的模式。...

  • 初始设计模式之原型模式

    原型模式是什么? 原型模式怎么用?浅拷贝深拷贝 原型模式再理解 一、原型模式是什么? ​ 原型模式是一种创建型设计...

  • PHP常用设计模式

    # 创建型 单例模式 工厂模式 工厂抽象模式 原型模式 建造者模式 # 结构型 # 行为型 # 3.注册模式 # ...

  • S3. 原型模式

    原型模式(Prototype) baidu[www.baidu.com] 原型模式是一种创建型设计模式,其功能为复...

  • iOS设计模式 (十三)原型模式

    概念 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.Prototype原型模式是一种创建型设计模...

网友评论

      本文标题:创建型-原型模式

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