设计模式之原型模式

一  预备知识

      1. 首先我们要知道 原型模式是设计模式中的创建型

       2.要了解原型模式我们要了解java 中的深拷贝和浅拷贝

       3. 定义:所谓原型模式,就是我们利用一个已有的对象,创建更多的相同类型的对象

疑问:这样创建和我们直接new有什么区别吗?

二 疑难解答

1. Java的浅拷贝

看下面的类(不是在编辑器上复制来的,不规范之处就那么地了)

class Book implements Clonable{

           private int price;

           private Author author;

           public Book clone(){

                   Book book = null;

                    try {

                               book = (Book) super.clone();

                      } catch (CloneNotSupportedException e) {

                          // TODO Auto-generated catch block

                          e.printStackTrace();

                         }

                        return book;

          }

            //一些get set 方法

}


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;

    }

}

可以看出Book类可以被克隆  Author 类不能被克隆

现在我们创建一个实例

Book book1 = new Book();

book1.setPrice(1);

Anthor author = new Author();

author.setXXX();

book1.setAuthor(author);


这里我们就把Book的属性的值都初始化完,

接下来我们对这个实例进行克隆

Book book2 = book1.clone();

这时候book2.getPrice() = book1.getPrice();

但是book1==book2 的值为false  因为在虚拟机堆中产生了两个实例,这两个引用指向的不是同一个对象。但是我们确把类Book的类型,属性值都拷贝过来了,这样和我们直接new Book相比,我们少了一些给新创建的对象赋值的操作,

注意我们上述复制称为浅复制,因为Book类有两个属性 price与Author

price是基本数据类型,所以我们的克隆来的对象中的price 也是新产生的int类型

而Author 是引用类型的对象,我们克隆的对象,只会产生一个指向原来的Author对象的引用,而不会重新在堆中创建一个实例(深复制与浅复制的区别就在这)

深复制中 引用类型的属性也就是Author,会在堆中又创建一个实例也就是下面的代码

Book中的浅复制

book1.getPrice() == book2.getPrice();  //结果为true

book1.getAuthor() == book2.getAuthor(); //结果为true

上面的复制过程中

内存中会有两个int大小的空间被占用,只有一个Author类型的空间会被占用

换句话说就是book1 中的 author = new Anthor();

book2 中 author = book1.author;

2. java中的深拷贝

Java中的深拷贝是通过序列化与反序列化来实现的。

还是上面的例子:

Book 与Author 都需要实现serializable接口

class Book implements Serializable{

           private int price;

           private Author author;


            public Book deepClone() throws IOException, ClassNotFoundException{

                    // 写入当前对象的二进制流

                    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 

                        ObjectOutputStream oos = new ObjectOutputStream(bos); 

                         oos.writeObject(this);


                        // 读出二进制流产生的新对象 

                         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); 

                         ObjectInputStream ois = new ObjectInputStream(bis); 

        return (Book) ois.readObject();

    }

//一些get set 方法

}

Author  仅仅是实现序列化接口 这里不写了


然后Book bk1 = new Book();

Book bk2 = bk1.deepClone();

这就是深复制 这里会复制一个Book的实例,同时Author类也会重现创建一个实例,

3. 原型模式

了解了Java中的深浅拷贝,我们就可以很容易理解原型模式了

换句话说Java中的深浅拷贝就是原型模式

我们回过头来看定义   就是我们利用一个已有的对象,创建更多的相同类型的对象

上述例子中Book 就是一个已知类型,我们通过克隆,创建了许多该对象的实例

同我们直接 new 相比我们省略了给他复制初始化的过程,简化了我们的开发,


4. 原型模式的有点与缺点

优点:1. 可以隐藏创建新对象的复杂性(这句话也说明 原型模式适合那些创建很复杂的对象,也适用与那些创建开销很大的对象)

           2. 在某些环境下,复制比创建高效

           3. 可扩展性好,依赖的是抽象

缺点:1.假设Author类中还有别的许多类,他们都要序列化,这就很麻烦

            2.  要为每一个类实现clone方法,对于已经存在的类,就很烦  违反了开闭原则


5. 原型模式结构


1.0 原型模式需要接口

interface YX{

    public Object clone();

}

2.0  需要复制的类要实现这个接口 方法

class Book implements YX{

public Object clone(){

   //实现

}


}

3.0 可以有多个实现,

4.0 原型模式的创建方式有两种:1简单型  2管理型  简单型  就是上面的例子

管理型就是新建一个类 用map来记录都创建了那些对象:map.set("对象1",book1)

下面是完整的浅克隆的例子

package com.jd.test;

//演示浅克隆

public class Bookimplements Cloneable {

private int price;

private int size;

public Book clone(){

Book bk =null;

try {

bk = (Book)super.clone();

}catch (CloneNotSupportedException e){

}

return bk;

}

public int getPrice() {

return price;

}

public void setPrice(int price) {

this.price = price;

}

public int getSize() {

return size;

}

public void setSize(int size) {

this.size = size;

}

@Override

    public String toString(){

return "Book.price = "+this.getPrice()+"  Book.size = "+this.getSize();

}

}

下面是主函数

package com.jd.test;

public class Main {

public static void main(String[] args) {

//  浅克隆

        Book b =new Book();

b.setPrice(1);

b.setSize(12);

System.out.println(b);

Book a = b.clone();

System.out.println(a);

}

}


下面是结果:

Book.price = 1  Book.size = 12

Book.price = 1  Book.size = 12

Process finished with exit code 0

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容

  • 原型模式(Prototype Pattern) 原型模式(Prototype Pattern)是用于创建重复的对象...
    thorhill阅读 1,039评论 0 2
  • 前言 在 Java 中,我们可以使用 new 关键字指定类名来生成类的实例。但是,有的时候,我们也会在不指定类名的...
    Kevin_ZGJ阅读 331评论 0 0
  • 原型模式的介绍 原型模式是一个创建型的模式,原型二字表明了该模式应该有一个样板实例,用户从这个样板对象中复制出一个...
    Android天之骄子阅读 350评论 0 0
  • 定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。 类型:创建类模式 类图: 原型模式主要用于对...
    郭某人1阅读 222评论 0 0
  • 感恩老天爷没有下雨! 感恩大爷上班把厂区的花草树木都修剪的整整齐齐,看着很漂亮,辛苦了! 感恩姐姐开车把公公送到医...
    一丢一丢阅读 95评论 0 0