一、概述:

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

简单的说就是对象的拷贝生成新的对象(对象的克隆),原型模式是一种对象创建型模式。

二、使用场景:

创建新的对象能够通过对已有对象进行复制来获得,假设是相似对象,则仅仅需对其成员变量稍作改动。

三、UML结构图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamFuaWNlMDUyOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

四、參与者

(1)    Prototype(抽象原型类):它是声明克隆方法的接口,是全部详细原型类的公共父类,能够是抽象类也能够是接口,甚至还能够是详细实现类。

(2)    ConcretePrototype(详细原型类):它实如今抽象原型类中声明的克隆方法。在克隆方法中返回自己的一个克隆对象。

(3)    Client(客户类):让一个原型对象克隆自身从而创建一个全新的对象。

五、用例学习:

1、抽象原型类:Prototype.java

/**
* 抽象原型类
* @author lvzb.software@qq.com
*
*/
public abstract class Prototype { /**
* 提供抽象克隆方法
*/
public abstract Prototype clone(); }

2、详细原型类:ConcretePrototypeA.java

/**
* 详细原型类A
* @author lvzb.software@qq.com
*
*/
public class ConcretePrototypeA extends Prototype { /**
* 浅克隆
*/
@Override
public Prototype clone() {
Prototype prototype = new ConcretePrototypeA();
return prototype;
} }

3、client測试类:Client.java

public class Client {

	public static void main(String[] args) {
Prototype prototypeA = new ConcretePrototypeA();
Prototype prototypeB = prototypeA.clone(); System.out.println(prototypeB.equals(prototypeA)); // return false
System.out.println(prototypeB == prototypeA); // return false
System.out.println(prototypeB.getClass() == prototypeA.getClass()); // return true } }

这里我们能够看到 prototypeA对象克隆了一个对象prototypeB,可是prototypeA  != prototypeB, 说明prototypeB是一个全新的Prototype对象。

注意:原型模式通过克隆方法所创建的对象是全新的对象,它们在内存中拥有新的地址,通常对克隆所产生的对象进行改动对原型对象不会造成不论什么影响。每个克隆对象都是相互独立的。

六、扩展:

关于浅克隆与深克隆的简介:

(1) 在Java语言中。数据类型分为值类型(基本数据类型)和引用类型。值类型包含int、double、byte、boolean、char等简单数据类型。引用类型包含类、接口、数组等复杂类型。

例如以下Person对象:

public class Person {
// 姓名
private String name;
// 年龄
private int age;
// 他的父亲
private Father father;
}

name、age 为基本数据类型,father就为引用类型。

浅克隆和深克隆的主要差别在于是否支持引用类型的成员变量的复制

(2)浅克隆:

在Java语言中。通过覆盖Object类的clone()方法就是实现浅克隆,在浅克隆中,当对象被复制时仅仅复制它本身和当中包括的值类型的成员变量。而引用类型的成员对象并没有复制。也就是说原型对象仅仅是将引用对象的地址复制一份给克隆对象,克隆对象和原型对象的引用类型成员变量还是指向同样的内存地址。

注意:可以实现克隆的Java类必须实现一个标识接口Cloneable,表示这个Java类支持被复制。假设一个类没有实现这个接口可是调用了clone()方法。Java编译器将抛出一个CloneNotSupportedException异常。

用代码说话:

1、引用对象:Father.java

public class Father{
// 姓名
private String name;
// 年龄
private int age; public Father(String name, int age) {
this.name = name;
this.age = 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;
} }

2、克隆原型类: Person.java

public class Person implements Cloneable{
// 姓名
private String name;
// 年龄
private int age;
// 他的父亲
private Father father; /**
* 重写 Object对象的clone方法实现Person对象的克隆
*/
public Person clone(){
Object obj = null;
try {
obj = super.clone();
return (Person)obj;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
} 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 Father getFather() {
return father;
} public void setFather(Father father) {
this.father = father;
}
}

3、測试类:CloneClient.java

public class CloneClient {

	public static void main(String[] args) {
Father father = new Father("老子", 50);
Person son = new Person();
son.setName("儿子");
son.setAge(24);
son.setFather(father); // 浅克隆出一个兄弟Person对象
Person brother = son.clone();
System.out.println(brother == son); // return false
System.out.println(brother.getFather() == son.getFather()); // return true
} }

以上 我们能够分析看到son 浅克隆出一个"兄弟"对象 brother,可是他们的引用对象"父亲"都是同一个对象,全部事实证明浅克隆没有对引用类型对象进行复制。

(3)深克隆:

在深克隆中。不管原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,简单来说,在深克隆中。除了对象本身被复制外,对象所包括的全部成员变量也将复制。

那么怎样实现深克隆呢?

在Java语言中。假设须要实现深克隆。能够通过序列化(Serialization)等方式来实现。序列化就是将对象写到流的过程。写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。

通过序列化实现的拷贝不仅能够复制对象本身,并且能够复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来。能够实现深克隆。须要注意的是能够实现序列化的对象其类必须实现Serializable接口。否则无法实现序列化操作。

用代码说话:

1、引用类:Father.java

import java.io.Serializable;

public class Father implements Serializable{
// 姓名
private String name;
// 年龄
private int age; public Father(String name, int age) {
this.name = name;
this.age = 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;
} }

2、克隆原型类: Person.java

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable; public class Person implements Serializable{
// 姓名
private String name;
// 年龄
private int age;
// 他的父亲
private Father father; /**
* 深克隆
* @return
* @throws IOException
* @throws ClassNotFoundException
* @throws OptionalDataException
*/
public Person deepClone() throws IOException, ClassNotFoundException, OptionalDataException
{
//将对象写入流中
ByteArrayOutputStream bao=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bao);
oos.writeObject(this); //将对象从流中取出
ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
return (Person) ois.readObject();
} 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 Father getFather() {
return father;
} public void setFather(Father father) {
this.father = father;
}
}

3、深克隆測试类:DeepCloneClient.java

public class DeepCloneClient {

	public static void main(String[] args) {
Father father = new Father("老子", 50);
Person son = new Person();
son.setName("儿子");
son.setAge(24);
son.setFather(father); try {
Person brother = son.deepClone();
System.out.println(brother == son); // false
System.out.println(brother.getFather() == son.getFather()); // false } catch (OptionalDataException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} } }

以上我们能够分析看到通过深克隆出来的"兄弟"对象brother 和 son 不仅不等、就连他们的引用类型Father也不等啦。

全部证明:通过深克隆 克隆出了一个全然独立的全新的对象。

JAVA设计模式之 原型模式【Prototype Pattern】的更多相关文章

  1. 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)

    原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...

  2. 二十四种设计模式:原型模式(Prototype Pattern)

    原型模式(Prototype Pattern) 介绍用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象.示例有一个Message实体类,现在要克隆它. MessageModel usin ...

  3. python 设计模式之原型模式 Prototype Pattern

    #引入 例子1: 孙悟空拔下一嘬猴毛,轻轻一吹就会变出好多的孙悟空来. 例子2:寄个快递下面是一个邮寄快递的场景:“给我寄个快递.”顾客说.“寄往什么地方?寄给……?”你问.“和上次差不多一样,只是邮 ...

  4. 【UE4 设计模式】原型模式 Prototype Pattern

    概述 描述 使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.如孙悟空猴毛分身.鸣人影之分身.剑光分化.无限剑制 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象, ...

  5. 设计模式系列之原型模式(Prototype Pattern)——对象的克隆

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  6. Net设计模式实例之原型模式( Prototype Pattern)

    一.原型模式简介(Brief Introduction) 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. Specify the kin ...

  7. java设计模式4——原型模式

    java设计模式4--原型模式 1.写在前面 本节内容与C++语言的复制构造函数.浅拷贝.深拷贝极为相似,因此建议学习者可以先了解C++的该部分的相关知识,或者学习完本节内容后,也去了解C++的相应内 ...

  8. 【设计模式】原型模式 Pototype Pattern

    前面讲了创建一个对象实例的方法单例模式Singleton Pattern, 创造多个产品的工厂模式(简单工厂模式 Simple Factory Pattern, 工厂方法模式 FactoryMothe ...

  9. JAVA 设计模式之原型模式

    目录 JAVA 设计模式之原型模式 简介 Java实现 1.浅拷贝 2.深拷贝 优缺点说明 1.优点 2.缺点 JAVA 设计模式之原型模式 简介 原型模式是六种创建型设计模式之一,主要应用于创建相同 ...

  10. java设计模式之原型模式

    原型模式概念 该模式的思想就是将一个对象作为原型,对其进行复制.克隆,产生一个和原对象类似的新对象.java中复制通过clone()实现的.clone中涉及深.浅复制.深.浅复制的概念如下: ⑴浅复制 ...

随机推荐

  1. 代理授权验证_web客户端授权验证

    HTTPPasswordMgrWithDefaultRealm() HTTPPasswordMgrWithDefaultRealm()类将创建一个密码管理对象,用来保存 HTTP 请求相关的用户名和密 ...

  2. DocView mode 3 -- 配置

    ;在当前页中滚动doc-view-continuous nil ;指定默认的字体大小doc-view-resolution ;gs生成的缓存的目录doc-view-cache-directory

  3. 6,id 小数据池,编码and解码。

    asscii :8位(数字,英文,特殊字符)表示一个字符. A:0000 0001 unicode :(万国码)初期:16位,两个字节,表示两个字符. A:0000 0001 0000 0001 中: ...

  4. pytest分布式执行(pytest-xdist)

    前言 平常我们手工测试用例非常多时,比如有1千条用例,假设每个用例执行需要1分钟.如果一个测试人员执行需要1000分钟才能执行完,当项目非常紧急的时候, 我们会用测试人力成本换取时间成本,这个时候多找 ...

  5. 【转载】linux之sed用法

    linux之sed用法 原文地址:http://www.cnblogs.com/dong008259/archive/2011/12/07/2279897.html   sed是一个很好的文件处理工具 ...

  6. hdu2074

    我先求出交叉的gird,然后再一行一行求得.感觉还可以吧.思路比较清晰,开始想的是数是第几行然后从每一行的前后开始控制,好麻烦的感觉,我就先求出来了框架再做就好做多啦!后来PE,突然发现我特殊处理n= ...

  7. 03-for循环in遍历

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  8. spring配置mybatis3

    mybatis官方网站:http://www.mybatis.org/mybatis-3/zh/configuration.html <!--第一步:加载配置数据库相关参数--> < ...

  9. mysql的row_number()实现

    在mysql中没有row_number()方法,这里模拟row_number()实现: 如有表 studentid   name age   class1 张1 15     12 张2 15     ...

  10. HDU——1045Fire Net(最大匹配)

    Fire Net Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...