原型模式(Prototype)

来源:互联网 发布:nfc扫描身份证软件 编辑:程序博客网 时间:2024/05/21 17:37

首先对原型模式进行一个简单概念说明:通过一个已经存在的对象,复制出更多的具有与此对象具有相同类型的新的对象。

在理解Java原型模式之前,首先需要理解Java中的一个概念:复制/克隆。

在博文《Java总结篇系列:java.lang.Object》一文中,对Java中的clone()方法进行了一定的阐述。同时,我们需要知道,Java中的对象复制/克隆分为浅复制和深复制。

一、浅复制:

我们知道,一个类的定义中包括属性和方法。属性用于表示对象的状态,方法用于表示对象所具有的行为。其中,属性既可以是Java中基本数据类型,也可以是引用类型。Java中的浅复制通常使用clone()方式完成。

当进浅复制时clone函数返回的是一个引用,指向的是新的clone出来的对象,此对象与原对象分别占用不同的堆空间。同时,复制出来的对象具有与原对象一致的状态。此处对象一致的状态是指:复制出的对象与原对象中的属性值完全相等==。

下面以复制一本书为例:

1.定义Book类和Author类:

复制代码
 1 class Author { 2  3     private String name; 4     private int age; 5  6     public String getName() { 7         return name; 8     } 9 10     public void setName(String name) {11         this.name = name;12     }13 14     public int getAge() {15         return age;16     }17 18     public void setAge(int age) {19         this.age = age;20     }21 22 }
复制代码
复制代码
 1 class Book implements Cloneable { 2  3     private String title; 4     private int pageNum; 5     private Author author; 6  7     public Book clone() { 8         Book book = null; 9         try {10             book = (Book) super.clone();11         } catch (CloneNotSupportedException e) {12             // TODO Auto-generated catch block13             e.printStackTrace();14         }15         return book;16     }17 18     public String getTitle() {19         return title;20     }21 22     public void setTitle(String title) {23         this.title = title;24     }25 26     public int getPageNum() {27         return pageNum;28     }29 30     public void setPageNum(int pageNum) {31         this.pageNum = pageNum;32     }33 34     public Author getAuthor() {35         return author;36     }37 38     public void setAuthor(Author author) {39         this.author = author;40     }41 42 }
复制代码

2.测试:

复制代码
 1 package com.qqyumidi; 2  3 public class PrototypeTest { 4  5     public static void main(String[] args) { 6         Book book1 = new Book(); 7         Author author = new Author(); 8         author.setName("corn"); 9         author.setAge(100);10         book1.setAuthor(author);11         book1.setTitle("好记性不如烂博客");12         book1.setPageNum(230);13 14         Book book2 = book1.clone();15         16         System.out.println(book1 == book2);  // false17         System.out.println(book1.getPageNum() == book2.getPageNum());   // true18         System.out.println(book1.getTitle() == book2.getTitle());        // true19         System.out.println(book1.getAuthor() == book2.getAuthor());        // true20         21     }22 }
复制代码

由输出的结果可以验证说到的结论。由此我们发现:虽然复制出来的对象重新在堆上开辟了内存空间,但是,对象中各属性确保持相等。对于基本数据类型很好理解,但对于引用数据类型来说,则意味着此引用类型的属性所指向的对象本身是相同的, 并没有重新开辟内存空间存储。换句话说,引用类型的属性所指向的对象并没有复制。

由此,我们将其称之为浅复制。当复制后的对象的引用类型的属性所指向的对象也重新得以复制,此时,称之为深复制。


二、深复制:

 Java中的深复制一般是通过对象的序列化和反序列化得以实现。序列化时,需要实现Serializable接口。

下面还是以Book为例,看下深复制的一般实现过程:

1.定义Book类和Author类注意:不仅Book类需要实现Serializable接口,Author同样也需要实现Serializable接口!!):

复制代码
 1 class Author implements Serializable{ 2  3     private String name; 4     private int age; 5  6     public String getName() { 7         return name; 8     } 9 10     public void setName(String name) {11         this.name = name;12     }13 14     public int getAge() {15         return age;16     }17 18     public void setAge(int age) {19         this.age = age;20     }21 22 }
复制代码
复制代码
 1 class Book implements Serializable { 2  3     private String title; 4     private int pageNum; 5     private Author author; 6  7     public Book deepClone() throws IOException, ClassNotFoundException{ 8         // 写入当前对象的二进制流  9         ByteArrayOutputStream bos = new ByteArrayOutputStream();  10         ObjectOutputStream oos = new ObjectOutputStream(bos);  11         oos.writeObject(this);12         13         // 读出二进制流产生的新对象  14         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  15         ObjectInputStream ois = new ObjectInputStream(bis);  16         return (Book) ois.readObject();17     }18     19     public String getTitle() {20         return title;21     }22 23     public void setTitle(String title) {24         this.title = title;25     }26 27     public int getPageNum() {28         return pageNum;29     }30 31     public void setPageNum(int pageNum) {32         this.pageNum = pageNum;33     }34 35     public Author getAuthor() {36         return author;37     }38 39     public void setAuthor(Author author) {40         this.author = author;41     }42 43 }
复制代码

2.测试:

复制代码
 1 public class PrototypeTest { 2  3     public static void main(String[] args) throws ClassNotFoundException, IOException { 4         Book book1 = new Book(); 5         Author author = new Author(); 6         author.setName("corn"); 7         author.setAge(100); 8         book1.setAuthor(author); 9         book1.setTitle("好记性不如烂博客");10         book1.setPageNum(230);11 12         Book book2 = book1.deepClone();13         14         System.out.println(book1 == book2);  // false15         System.out.println(book1.getPageNum() == book2.getPageNum());   // true16         System.out.println(book1.getTitle() == book2.getTitle());        // false17         System.out.println(book1.getAuthor() == book2.getAuthor());        // false18         19     }20 }
复制代码

从输出结果中可以看出,深复制不仅在堆内存上开辟了空间以存储复制出的对象,甚至连对象中的引用类型的属性所指向的对象也得以复制,重新开辟了堆空间存储。

 

至此:设计模式中的创建型模式总结完毕,一共有五种创建型模式,分别为:单例模式(SingleTon)、建造者模式(Builder)、工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)和原型模式(Prototype)。每种模式适用于不同的场景,具体应用时需注意区分。

三、原文博客地址

http://www.cnblogs.com/lwbqqyumidi/p/3746821.html

0 0