What

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

Why

Prototype适用于在一个类的实例有几种不同的状态组合的一种时,建立相应的数目的原型并克隆她们,要比每次使用合适的状态创建它们方便一些,或者为了避免创建一个与产品类层次平行的工厂类层次时,要实例化一的类在运行时动态指定时。

How

假设如下场景:有一个复杂的报表,创建过程非常复杂,需要把报表发给两个领导,其中只有报表少了属性不同,其他属性相同。

首先讨论一下java中的基础知识

java的clone()方法:

clone方法将对象复制一份并返回给调用者。一般满足如下条件:

1、对于任何对象a,都有a.clone()!=x,克隆对象和源对象是不同的对象

2、对于任何对象a,都有a.clone().getClass()==a.getClass(),克隆对象和源对象类型一样

3、如果对象a的equals()方法定义恰当,那么a.clone().equals(a)成立。

java中对象克隆的实现:

可以利用Object类的clone()方法

1、对象类实现Coneable接口

2、覆盖实现clone()方法

3、调用super.clone(),实现克隆。

以上场景实现代码如下:

public class Product implements Cloneable{

    private String name;

    private int model;

    public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getModel() {
return model;
} public void setModel(int model) {
this.model = model;
} @Override
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
public class Report implements Cloneable{

    private String name;

    private Product product;

    public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Product getProduct() {
return product;
} public void setProduct(Product product) {
this.product = product;
} @Override
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}

客户端调用

public class App {
public static void main( String[] args ){
Report report=new Report();
Product product=new Product();
product.setModel(1);
product.setName("productName");
report.setName("某某产品报表");
report.setProduct(product);
System.out.println(report.getName()+"|"+report.getProduct().getName());
Report report1=(Report)report.clone();
report1.setName("某某产品报表组1");
report1.getProduct().setName("产品1");
System.out.println(report1.getName()+"|"+report1.getProduct().getName());
}
}

以上代码类图如下:

Discuss

深拷贝VS浅拷贝

以上的例子我们的运行结果如下:

某某产品报表|productName
某某产品报表组1|产品1

我们在加一行代码,在最后一行打印report的信息

System.out.println(report.getName()+"|"+report.getProduct().getName());

我们的运行结果如下:

某某产品报表|productName
某某产品报表组1|产品1
某某产品报表|产品1

我们可以看出,第二次打印的结果出了问题,report中的产品名字已经被改变了。

在Report中,其中product属性,我们引用其他对象,在clone方法中,我们的实现只复制了它的引用,只负责了它的指针,没有复制它所指向的堆空间里的属性,所以在这行代码report1.getProduct().setName("产品1");也改变了report中product属性中的name属性的值,这种拷贝是浅拷贝。

我们修改下report的clone()方法,改为如下:

    @Override
protected Object clone() {
Report report;
try {
report=(Report) super.clone();
report.setProduct((Product)product.clone());
return report;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}

我们再看下运行结果

某某产品报表|productName
某某产品报表组1|产品1
某某产品报表|productName

这次结果正确了,在以上代码中,我们对product属性,也进行了一次clone,所以report1和report的product属性指向了不同的堆空间,所以我们改变product中的属性值,不会相互影响,这个拷贝就是深拷贝。

设计模式学习--Prototype的更多相关文章

  1. 设计模式学习系列6 原型模式(prototype)

    原型模式(prototype)用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.允许一个对象再创建另外一个新对象的时候根本无需知道任何创建细节,只需要请求圆形对象的copy函数皆可. 1 ...

  2. [学习笔记]设计模式之Prototype

    写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 在笔记Builder模式中,我们曾见到了最初用于创建平行世界的函数createWorld,并且它是Mage类的成员函数(毕竟是专属于魔 ...

  3. python之路,Day24 常用设计模式学习

    python之路,Day24 常用设计模式学习   本节内容 设计模式介绍 设计模式分类 设计模式6大原则 1.设计模式介绍 设计模式(Design Patterns) --可复用面向对象软件的基础 ...

  4. Java设计模式学习记录-GoF设计模式概述

    前言 最近要开始学习设计模式了,以前是偶尔会看看设计模式的书或是在网上翻到了某种设计模式,就顺便看看,也没有仔细的学习过.前段时间看完了JVM的知识,然后就想着JVM那么费劲的东西都看完了,说明自己学 ...

  5. swift设计模式学习 - 原型模式

    移动端访问不佳,请访问我的个人博客 设计模式学习的demo地址,欢迎大家学习交流 原型模式 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 定义 用原型实例指定创建对象的种类,并且通 ...

  6. C#大话设计模式学习总结

    如有雷同,不胜荣欣,如转载,请注明 C#大话设计模式学习总结 一.工厂模式 面向对象的三个特性:封装,继承和多态 1.封装 Class Operate { privatedouble _numberA ...

  7. 7 种 Javascript 常用设计模式学习笔记

    7 种 Javascript 常用设计模式学习笔记 由于 JS 或者前端的场景限制,并不是 23 种设计模式都常用. 有的是没有使用场景,有的模式使用场景非常少,所以只是列举 7 个常见的模式 本文的 ...

  8. Java-马士兵设计模式学习笔记-总结

    <马士兵设计模式学习>学习了以下模式: 1.装饰者模式(例子:水管工,木工) 2.策略模式(例子:老师用职称比大小.学生用成绩比大小) 3.简单工厂模式(例子:VechileFactory ...

  9. Java设计模式学习资源汇总

    本文记录了Java设计模式学习书籍.教程资源.此分享会持续更新: 1. 设计模式书籍 在豆瓣上搜索了一把,发现设计模式贯穿了人类生活的方方面面.还是回到Java与程序设计来吧. 打算先归类,再浏览,从 ...

随机推荐

  1. windows多线程同步互斥--总结

    我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同步--临界区 windows多线程同步 ...

  2. 〖Linux〗Ubuntu用户重命名、组重命名,机器重命名~

    有时候得到的一台机器名字并不是自己熟悉的,或许是你只是想希望修改一下用户名等等-- 步入正题,其实很简单的,重启机器之后不要进入桌面,按下Ctrl+Alt+F1,使用Root登录,执行以下命令: # ...

  3. mongodb用户管理和服务安装

    一.忘记密码快速找回 任何系统忘记密码都是一样的操作:以无需授权的模式开启程序,然后进入系统修改权限设置,退出来重新以授权方式开启程序.MySQL是这样,MongoDB也是这样.好的系统都提供了无授权 ...

  4. LaTeX 中使两张表格并排

    在使用 LaTeX写论文或者画海报的时候,希望两张较小的表格可以并排,(一般情况的LaTeX插入两张图片是上下布局的) 查找了一下,相关的例子如下: \begin{minipage}{\textwid ...

  5. codeblocks技巧收集

    Ctrl+Shift+C  注释代码块 Ctrl+Shift+X  取消注释

  6. 升级python(linux)

    查看系统当前python版本 2: [root@wangyuelou ~]# python     Python 2.4.3 (#1, May  5 2011, 16:39:10)     [GCC ...

  7. Asp.Net T4模板生成三层架构

    1.T4 Editor安装 T4:根据模板生成文件,例如model等 vs中默认t4模板编码是没有提示和高亮的,需使用以下插件,免费的 https://t4-editor.tangible-engin ...

  8. 【九天教您南方cass 9.1】 03 编码法绘制地形图

    同学们大家好,欢迎收看由老王测量上班记出品的cass9.1视频课程 我是本节课主讲老师九天. 测量空间的[九天教您南方cass]专栏是九天老师专门开设cass免费教学班.希望能帮助那些刚入行的同学,并 ...

  9. 【九天教您南方cass 9.1】 07 绘制与标注圆曲线和细部点的方法

    同学们大家好,欢迎收看由老王测量上班记出品的cass9.1视频课程 我是本节课主讲老师九天. 我们讲课的教程附件也是共享的,请注意索取测量空间中. [点击索取cass教程]5元立得 (给客服说暗号:“ ...

  10. Visual Studio TFS Branching and Merging Guidance

    Origin URL:https://msdn.microsoft.com/en-us/magazine/gg598921.aspx Bill Heys and Willy-Peter Schaub ...