一、概述:

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

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

二、使用场景:

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

三、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. LeetCode(111) Minimum Depth of Binary Tree

    题目 Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the s ...

  2. 关于Linux下使用expdp和impdp命令对Oracle数据库进行导入和导出操作

    说明:本次导入和导出采用expdp和impdp命令进行操作,这2个命令均需要在服务器端进行操作 http://www.cnblogs.com/huacw/p/3888807.html 一.    从O ...

  3. luogu2569 [SCOI2010]股票交易

    题解看这里 #include <iostream> #include <cstring> #include <cstdio> using namespace std ...

  4. android 之 TabHost

    TabHost的实现有两种方式,第一种继承TabActivity,从TabActivity中用getTabHost()方法获取TabHost.各个Tab中的内容在布局文件中定义就行了. mainAct ...

  5. rabbitmq php扩展amqp安装

    configure: error: Please reinstall the librabbitmq distribution itself or (re)install librabbitmq de ...

  6. Dialog共通写法(两个button)

    package jp.co.hyakujushibank.view import android.app.Dialogimport android.content.Contextimport andr ...

  7. 【Openjudge】岛屿(并查集)

    题目链接 此题是并查集.考虑到水位不断上涨,所以将时间倒转.先统计最后一天的联通块个数,每一天浮出水面的块进行计算.复杂度O(玄学). 代码如下 #include<cstdio> #inc ...

  8. BZOJ 3309 DZY Loves Math ——莫比乌斯反演

    枚举$d=gcd(i,j)$ 然后大力反演 ——来自Popoqqq的博客. 然后大力讨论后面的函数的意义即可. http://blog.csdn.net/popoqqq/article/details ...

  9. 浅谈java内存泄漏

    最近有朋友遇到个问题,tomcat在运行几天后就会报outofmemory,然后就死了,我就稍微总结了下内存泄漏的一些原因,纯属个人理解,欢迎大侠们劈砖: 一.字符串问题 这个也是一个常见的问题,我们 ...

  10. angular父子scope之间的访问

    1.子可以访问父的scope,也可以更新相同的scope,但父scope不会被刷新 2.父要访问子scope的方法