Chapter 9 原型模式
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 简单的说就是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 原型模式的更多相关文章
- 设计模式(六)原型模式(Prototype Pattern)
一.引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在 ...
- PHP 原型模式
原型模式:原型模式是先创建好一个原型对象,然后通过拷贝原型对象来创建新的对象.适用于大对象的创建,因为创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需内存拷贝即可.也可以用作动态 ...
- C#设计模式:原型模式(Prototype)及深拷贝、浅拷贝
原型模式(Prototype) 定义: 原型模式:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象.被复制的实例被称为原型,这个原型是可定制的. Prototype Pattern也是一 ...
- 设计模式--原型模式Prototype(创建型)
一.原型模式 用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象.原型模式实现的关键就是实现Clone函数,还需要实现深拷贝. 二.UML类图 三.例子 //父类 class Resume ...
- C#设计模式之原型模式
原型模式:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象. 分析: 孙悟空:根据自己的形状复制(克隆)出多个身外身 软件开发:通过复制一个原型对象得到多个与原型对象一模一样的新对 ...
- 设计模式 之 原型模式(ProtoType)
什么时原型模式 或 原型模式的定义: 用原型实例来指定创建对象的种类,并通过拷贝这些原型创建新的对象. 原型模式的特点: 1),它是面向接口编程, 2),原型模式的新对象是对原型实例的一个克隆 ...
- Objective-C 原型模式 -- 简单介绍和使用
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. Prototype原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建 ...
- C#设计模式-原型模式
在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在内存中分配 ...
- C#设计模式系列:原型模式(Prototype)
1.原型模式简介 1.1>.定义 原型模式(Prototype)用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象. 1.2>.使用频率 中 1.3>.原型模式应用 首先 ...
随机推荐
- OutputDebugString 输出信息到调试器
#include <Windows.h>#include <stdio.h>#include <stdarg.h> void __cdecl odprintf(co ...
- SQLITE 多进程查询出错database is locked
程序比较简单: 父进程查询数据库A表,没有更新操作 子进程同时查询数据库A表,查询出来的内容更新B表. 两个进程都放到while(1)循环中,速度慢的话就是2S执行一次就没有错,执行的速度快的话就会报 ...
- 在OSX狮子(Lion)上安装MYSQL(Install MySQL on Mac OSX)
这篇文章简述了在Mac OSX狮子(Lion)上安装MySQL Community Server最新版本v10.6.7的过程. MySQL是最流行的开源数据库管理系统.首先,从MySQL的下载页面上下 ...
- 宣布在 Azure 镜像库中正式推出 Windows Server 2012 R2 并降低 Windows Azure 的实例定价
我们今天将宣布两条消息,为使用基础结构服务的客户提供更多选择和成本节约:在镜像库中推出 Windows Server 2012 R2 以及降低 Memory Intensive 计算实例定价. 虚拟机 ...
- JAVA GUI学习 - JProgressBar进度条组件摘录
public class JProgressBarTest extends JFrame{ public JProgressBarTest() { super(); setTitle("表格 ...
- installation - How to install Synaptic Package Manager? - Ask Ubuntu
installation - How to install Synaptic Package Manager? - Ask Ubuntu How to install Synaptic Package ...
- HDU 4521 小明系列问题——小明序列 (线段树维护DP)
题目地址:HDU 4521 基本思路是DP.找前面数的最大值时能够用线段树来维护节省时间. 因为间隔要大于d. 所以能够用一个队列来延迟更新,来保证每次询问到的都是d个之前的. 代码例如以下: #in ...
- python第三方模块
python相关:1.zeromq网络库:2.twisted框架:twisted:一个基于事件驱动,异步的python高性能网络开发框架:注:什么是基于事件驱动:当(鼠标点击事件)事件注册器注入事件, ...
- bootstrap固定响应式导航
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.2.0/css/bootstrap. ...
- CSS的position(位置)
position: 位置,absolute绝对位置,相对于浏览器边界的位置:relative相对位置,相对于它本应该出现的位置.fixed:固定位置,它不会随着滚动. 设置好position之后,就可 ...