原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 简单的说就是clone一个对象实例。使得clone出来的copy和原有的对象一模一样。 插一个简单使用clone的例子,如果一个对象内部有可变对象实例的话,public API不应该直接返回该对象的引用,以防调用方的code改变该对象的内部状态。这个时候可以返回该对象的clone。 一般而言,我们要的clone应该是这样的。copy和原型的内容一样,但是又是彼此隔离的。即在clone之后,改变其中一个不影响另外一个。

原型模式分为浅复制和深复制,其中浅复制:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。深复制把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。

class User {
String name;
int age;
}
class Account implements Cloneable {
User user;
long balance;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

我们之所以要深copy,是因为默认的实现提供的浅copy不是隔离的,换言之,改变copy的东西,会影响到原型的内部。比如例子中,改变copy的user的name,影响了原型。特别注意的是string是一种拥有值类型特点的特殊引用类型。
class User implements Cloneable {
String name;
int age;
@Override
public User clone() throws CloneNotSupportedException {
return (User) super.clone();
}
}
class Account implements Cloneable {
User user;
long balance;
@Override
public Account clone() throws CloneNotSupportedException {
Account account = null;
account = (Account) super.clone();
if (user != null) {
account.user = user.clone();
}
return account;
}
}

再来贴2个实例代码

一、浅复制:

package xiao;

class WorkExp{

private String workDate;

private String company;

public String getWorkDate() {

return workDate;

}

public void setWorkDate(String workDate) {

this.workDate = workDate;

}

public String getCompany() {

return company;

}

public void setCompany(String company) {

this.company = company;

}

}

class Resume implements Cloneable{

private String name;

private String sex;

private String age;

private WorkExp work;

public Resume(String name){

this.name = name;

work = new WorkExp();

}

public void setPerInfo(String sex,String age){

this.sex = sex;

this.age = age;

}

public void setWorkExper(String timeArea,String company){

work.setWorkDate(timeArea);

work.setCompany(company);

}

public void display(){

System.out.println(this.name+" "+this.sex+" "+this.age);

System.out.println(work.getWorkDate()+" "+work.getCompany());

}

public Object clone() throws CloneNotSupportedException {

return super.clone();

}

}

public class Hello {

public static void main(String[] args) throws Exception{

Resume a = new Resume("big bird");

a.setPerInfo("male", "20");

a.setWorkExper("1998-2006", "IT company");

Resume b = (Resume)a.clone();

b.setWorkExper("1998-2004", "YY company");

Resume c = (Resume)a.clone();

c.setPerInfo("female", "22");

c.setWorkExper("1998-2004", "ZZ company");

a.display();

b.display();

c.display();

}

}

输出:

big bird male 20
1998-2006 ZZ company
big bird male 20
1998-2004 ZZ company
big bird female 22
1998-2004 ZZ company

二、深复制:


package xiao;


class WorkExp implements Cloneable{
private String workDate;
private String company;
public String getWorkDate() {
return workDate;
}
public void setWorkDate(String workDate) {
this.workDate = workDate;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public WorkExp clone() throws CloneNotSupportedException {
return (WorkExp)super.clone();
}
}
class Resume implements Cloneable{
private String name;
private String sex;
private String age;
private WorkExp work;
public Resume(String name){
this.name = name;
work = new WorkExp();
}
public void setPerInfo(String sex,String age){
this.sex = sex;
this.age = age;
}
public void setWorkExper(String timeArea,String company){
work.setWorkDate(timeArea);
work.setCompany(company);
}
public void display(){
System.out.println(this.name+" "+this.sex+" "+this.age);
System.out.println(work.getWorkDate()+" "+work.getCompany());
}
public Resume clone() throws CloneNotSupportedException {
Resume resume = null;
resume = (Resume) super.clone();
if(work != null){
resume.work = work.clone();
}
return resume;
}
}
public class Hello {


public static void main(String[] args) throws Exception{
Resume a = new Resume("big bird");
a.setPerInfo("male", "20");
a.setWorkExper("1998-2006", "IT company");
Resume b = (Resume)a.clone();
b.setWorkExper("1998-2004", "YY company");
Resume c = (Resume)a.clone();
c.setPerInfo("female", "22");
c.setWorkExper("1998-2004", "ZZ company");
a.display();
b.display();
c.display();
}
}

输出:

big bird male 20
1998-2006 IT company
big bird male 20
1998-2004 YY company
big bird female 22
1998-2004 ZZ company

Chapter 9 原型模式的更多相关文章

  1. 设计模式(六)原型模式(Prototype Pattern)

    一.引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在 ...

  2. PHP 原型模式

    原型模式:原型模式是先创建好一个原型对象,然后通过拷贝原型对象来创建新的对象.适用于大对象的创建,因为创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需内存拷贝即可.也可以用作动态 ...

  3. C#设计模式:原型模式(Prototype)及深拷贝、浅拷贝

    原型模式(Prototype) 定义: 原型模式:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象.被复制的实例被称为原型,这个原型是可定制的. Prototype Pattern也是一 ...

  4. 设计模式--原型模式Prototype(创建型)

    一.原型模式 用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象.原型模式实现的关键就是实现Clone函数,还需要实现深拷贝. 二.UML类图 三.例子 //父类 class Resume ...

  5. C#设计模式之原型模式

    原型模式:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象. 分析: 孙悟空:根据自己的形状复制(克隆)出多个身外身 软件开发:通过复制一个原型对象得到多个与原型对象一模一样的新对 ...

  6. 设计模式 之 原型模式(ProtoType)

    什么时原型模式   或   原型模式的定义: 用原型实例来指定创建对象的种类,并通过拷贝这些原型创建新的对象. 原型模式的特点: 1),它是面向接口编程, 2),原型模式的新对象是对原型实例的一个克隆 ...

  7. Objective-C 原型模式 -- 简单介绍和使用

    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. Prototype原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建 ...

  8. C#设计模式-原型模式

    在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在内存中分配 ...

  9. C#设计模式系列:原型模式(Prototype)

    1.原型模式简介 1.1>.定义 原型模式(Prototype)用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象. 1.2>.使用频率 中 1.3>.原型模式应用 首先 ...

随机推荐

  1. BZOJ 2761 不重复数字 (Hash)

    题解:直接使用STL中的hash去重即可 #include <cstdio> #include <map> using namespace std; int ans[50010 ...

  2. [cocos2dx笔记011]使用Cocostudio UI编辑器

    本文地址:http://www.cppblog.com/zdhsoft/archive/2014/07/19/207715.html 笔记汇总:http://www.cppblog.com/zdhso ...

  3. FastReport配置打印预览button_C++

    如需转载请标明出处:http://blog.csdn.net/itas109 FastReport採用C++方式.配置打印预览选项 //打印预览 //配置打印预览选项 pReport->Prev ...

  4. junit学习笔记(二):hamcrest和TestSuit

    1. hamcrest hamcrest可以有效增加junit的测试能力,用一些对通俗语言来进行测试. Hamcrest 是一个测试的框架,它提供了一套通用的匹配符 Matcher,灵活使用这些匹配符 ...

  5. HTTP学习笔记--HTTP报文

    报文流     HTTP报文在客户端.服务器和代理之间流动.“流入”.“流出”.“上游”.“下游”这些术语用来描述报文方向. 报文流入源端服务器     流入:流向服务器     流出:流向用户Age ...

  6. exists

    select count(*) from Table_A where exists (select count(*) from Table_B.Column1 = Table_A.Column1) 该 ...

  7. Tableau Server 8.0 升级到 8.3 过程记录

    一.使用账号(管理员权限),安装文件复制到服务器 二.检查维护状态 如果维护状态过期,更新到新版本会变成未授权. 先进Manage Product Keys刷新一下维护日期(其实不刷新也无所谓.到时候 ...

  8. 使用jsonEditor打造一个复杂json编辑器

    最近研究一个web版的json编辑器,在github中搜索,发现了这个利器. https://github.com/jdorn/json-editor 几经研究,终于把该控件的大部分功能研究透彻. 发 ...

  9. IOS开发:UIAlertView使用

    链接地址:http://www.2cto.com/kf/201307/231841.html UIAlertView是什么就不介绍了 1.基本用法 1 UIAlertView *view = [[UI ...

  10. 「OC」内存管理

    一.基本原理 (一)为什么要进行内存管理. 由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空 ...