一天学习一个设计模式之原型模式

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

  原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。例如:有一张个人简历(此为具体原型),需要在这个基础上复印十份简历。如果不复印,那就得手写10份简历,耗时耗力。这就是原型模式所表现出来的优势。具体代码如下:

1 /**
2  * 抽象原型角色,这是一个抽象角色,通常由一个JAVA接口或JAVA抽象类实现。
3  * 此角色给出所有的暗送秋波原型类所需要的接口
4  */
5 public interface IPrototype {
6     IPrototype clone();
7     String getId();
8     void setId(String id);
9 }
 1 /**
 2  * 具体原型角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口
 3  */
 4 public class ConcretePrototype1 implements IPrototype {
 5     private String id;
 6     @Override
 7     public IPrototype clone() {
 8         ConcretePrototype1 prototype=new ConcretePrototype1();
 9         prototype.setId(this.id);
10         return prototype;
11     }
12
13     @Override
14     public String getId() {
15         return id;
16     }
17
18     @Override
19     public void setId(String id) {
20         this.id=id;
21     }
22 }
 1 /**
 2  * 客户(Client)角色:客户类提出创建对象的请求。
 3  */
 4 public class Client {
 5     public static void main(String[] args) {
 6         IPrototype p1=new ConcretePrototype1();
 7         p1.setId("9527");
 8         System.out.println(p1.getId());
 9         IPrototype c1=p1.clone();
10         System.out.println(c1.getId());
11         IPrototype c2=p1.clone();
12         System.out.println(c2.getId());
13         System.out.println(p1==c1);
14         System.out.println(c1==c2);
15     }
16 }

注意:为什么要用IPrototype c1=p1.clone();而不是IPrototype c1=p1呢?如果这样做的话,模拟到现实的简历就相当于在另外10份简历上没有你的个人信息,而是相当于写一串文字“我的简历在我的手上,请联系我”,哈哈.....

浅克隆和深克隆

无论你是自己实现克隆方法,还是采用Java提供的克隆方法,都存在一个浅度克隆和深度克隆的问题。

1、浅克隆

  只负责克隆按值传递的数据(比如基本数据类型、String类型),而不是复制它所引用的对象,换言之,所有的对其他对象的引用都仍然指向原来的对象。

2、深克隆

  除了浅克隆要克隆的值外,还负责克隆引用类型的数据。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深克隆把要复制的对象所引用的对象都复制了一遍,而这种对被引用到的对象的复制叫做间接复制。

利用序列化实现深度克隆

  把对象写到流里的过程是序列化(Serialization)过程;而把对象从流中读出来的过程则叫反序列化(Deserialization)过程。应当指出的是,写到流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。

  在Java语言里深度克隆一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的拷贝)写到一个流里(序列化),再从流里读回来(反序列化),便可以重建对象。

  这样做的前提就是对象以及对象内部所有引用到的对象都是可序列化的,否则,就需要仔细考察那些不可序列化的对象可否设成transient,从而将之排除在复制过程之外。

  浅度克隆显然比深度克隆更容易实现,因为Java语言的所有类都会继承一个clone()方法,而这个clone()方法所做的正式浅度克隆。

  有一些对象,比如线程(Thread)对象或Socket对象,是不能简单复制或共享的。不管是使用浅度克隆还是深度克隆,只要涉及这样的间接对象,就必须把间接对象设成transient而不予复制;或者由程序自行创建出相当的同种对象,权且当做复制件使用。

  

原型模式的优点

  原型模式允许在运行时动态改变具体的实现类型。原型模式可以在运行期间,由客户来注册符合原型接口的实现类型,也可以动态地改变具体的实现类型,看起来接口没有任何变化,但其实运行的已经是另外一个类实例了。因为克隆一个原型就类似于实例化一个类。

原型模式的缺点

  原型模式最主要的缺点是每一个类都必须配备一个克隆方法。配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类来说不是很难,而对于已经有的类不一定很容易,特别是当一个类引用不支持序列化的间接对象,或者引用含有循环结构的时候。

时间: 2024-10-05 00:15:21

一天学习一个设计模式之原型模式的相关文章

Java学习笔记——设计模式之六.原型模式(浅克隆和深克隆)

That there's some good in this world, Mr. Frodo. And it's worth fighting for. 原型模式(prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 至于Object.clone()这里就不赘述了.文档看起来可能有些难懂,直接上代码反而更容易理解: 浅克隆: 1 package cn.happy.design_pattern._06prototype.shallowclone; 2 3 pub

一天学习一个设计模式之迭代器模式

迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示. 当需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,就应该考虑用迭代器模式,需要对聚集有多种方式遍历时,也可以考虑用迭代器模式.为遍历不同的聚集结构提供如开始.下一个.是否结束.当前哪一项等统一接口.迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器来负责,这样既可以做到不暴露集合的内部结构,又可让外部透明地访问集合内部的数据. 代码如下: 1 /** 2 * 迭代器抽象类

【设计模式】——原型模式

原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 下图是原型模式的结构图: 原型模型其实就是一个对象再创建另外一个可定制的对象,而且不需任何创建的细节,我们来看看基本的原型模式代码. //原型类 class Prototype { private: string id; public: Prototype(string id) { this->id=id; } string GetId() { return id; } virtual Protot

大话设计模式_原型模式(Java代码)

原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 简单描述:即通过实现接口Cloneable重写方法clone(),使得创建新的拷贝对象不需要一个成员一个成员的重新复制,而且可以提高创建对象的效率 Java中要想实现拷贝使用clone()方法,类必须实现Cloneable接口,并且重写Object类中的clone()方法,调用父类的clone()方法即可实现浅复制 代码如下: WorkExperience类: 1 package com.longsheng.prototy

大话设计模式之原型模式

原型模式 定义: 用原型实例制定创建对象的种类,并通过拷贝这些原型,创建新的对象. 实质: 就是从一个对象在创建另一个可定制的对象,而且不需要知道任何创建的细节. 核心: (1).实现Cloneable接口,可以使用此接口的类上使用clone方法. (2).重写Object类中的clone方法,因为所有类的父类是Object类,Object有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,将clone改为public类型. 结构图: 代

深入浅出设计模式 ------ Prototype(原型模式)之深度克隆

继上篇深入浅出设计模式 ------ Prototype(原型模式)的浅克隆实现, 本文进入Prototype(原型模式)的进阶篇----深度克隆. 深度克隆 ---- 序列化方式实现 把对象写到流里的过程是序列化(Serilization)过程,而把对象从流中读出来的过程则叫做反序列化(Deserialization).写在流里的是对象的一个克隆(新的, 独立的), 而原对象仍存在于JVM内存模型里.因此, 以下代码采用序列化方式实现深度克隆. 第一步: 将上篇的代码做些许改动, 加入对象引用

C#设计模式(6)——原型模式(Prototype Pattern)

一.引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在内存中分配了多个一样的类实例对象,然后如果采用工厂模式来创建这样的系统的话,随着产品类的不断增加,导致子类的数量不断增多,反而增加了系统复杂程度,所以在这里使用工厂模式来封装类创建过程并不合适,然而原型模式可以很好地解决这个问题,因为每个类实例都是相同的,当我们需要多个相同的类实例时,没必要每次都使

图解Java设计模式之原型模式

图解Java设计模式之原型模式 克隆羊的问题 原型模式 - 基本介绍 原型模式在Spring框架中源码分析 浅拷贝的介绍 深拷贝基本介绍 克隆羊的问题 现在有一只羊tom,姓名为 : tom,年龄为 :1,颜色为 :白色,请编写程序创建和tom羊属性完全相同的10只羊. 传统方式解决克隆羊的问题 package com.example.demo.prototype; public class Sheep { private String name; private int age; privat

每天一个设计模式-7 生成器模式(Builder)

每天一个设计模式-7 生成器模式(Builder) 一.实际问题 在讨论工厂方法模式的时候,提到了一个导出数据的应用框架,但是并没有涉及到导出数据的具体实现,这次通过生成器模式来简单实现导出成文本,Xml等具体的格式. 导出成文本或Xml等格式的数据时,一般都会有各自的格式,比如:导出的文件都有3个部分,文件头,内容,尾. 二.问题分析 无论哪种导出格式,都需要3个部分,文件头,内容,尾等信息,并且他们的内容相同.即他们的构造算法固定,只是生成的结果不同:能不能把算法(构建)和结果(外观)分离出