03 原型模式(prototype)

1 克隆羊问题

现在有一只羊tom,姓名为: tom。年龄为: 1,颜色为:白色,请编写程序创建和tom羊属性完全相同的10只羊。

2 传统方式解决
  • 思路

    classDiagram
    Client ..> Sheep : 依赖
    class Client{

    }
    class Sheep{
    name String
    age int
    }

    new十只羊出来。

3 传统方式优缺点
  • 优点是比较好理解,简单易操作。
  • 在创建新的对象时,总是需要重新获取原始对象的属性,如果创建的对象比较复杂时,效率较低总是需要重新初始化对象,而不是动态地获得对象运行时的状态。不够灵活
4 改进的思路分析
  • Java中 Object类是所有类的根类,Object类提供了一个clone()方法,该方法可以将一个Java对象复制一份,但是需要实现clone的Java类必须要实现一个接口Cloneable,该接口表示该类能够复制且具有复制的能力→原型模式
5 原型模式
  • 原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象

  • 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节

  • 工作原理是:通过将一个原型对象传给要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即object.clone()

  • 原理结构图类图

    classDiagram
    ConcretePrototype1 ..|> Prototype
    ConcretePrototype2 ..|> Prototype
    Client ..> Prototype
    class Client{

    }
    class Prototype{
    +Clone()
    }
    class ConcretePrototype1{
    +Clone()
    }
    class ConcretePrototype2{
    +Clone()
    }

    原理结构图说明

    • Prototype:原型类,声明一个克隆自己的接口
    • ConcretePrototype:具体的原型类,实现一个克隆自己的操作
    • Client:让一个原型对象克隆自己,从而创建一个新的对象(属性一样)
6 浅拷贝
  • 对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。

  • 对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。

  • 因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。

  • 浅拷贝是使用默认的clone()方法来实现的。

    sheep = (Sheep)super.clone();
7 深拷贝
  • 复制对象的所有基本数据类型的成员变量值

  • 为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象进行拷贝

  • 深拷贝实现方式

    • 重写clone方法来实现深拷贝。
    • 通过对象序列化实现深拷贝(推荐)
    //DeepPrototyped的引用类型
    class DeepCloneTarget implements Serializable, Cloneable
    {
    private static final long serialVersionUID = 1L;
    private String cloneName;
    private String cloneClass;
    //构造器
    public DeepCloneableTarget(String cloneName, String cloneClass){
    this.cloncName = cloncName;
    this.cloneClass = cloneClass;
    }
    //因为该类的属性,都是String,因此我们这里使用默认的clone完成即可
    @Override
    protected Object clonc() throws CloncNotSupportedException {
    return super.clone();
    }
    ) class DeepPrototype{
    public String name; // String属性
    public DeepCloneableTarget deepCloneableTarget;// 引用类型
    public DeepProtoType( {
    super();
    } //深拷贝-方式1使用clone方法
    @override
    protected 0bject clone() throws cloneNotSupportedException {
    object deep = null;
    //这里完成对基本数据类型(属性)和String的克隆deep = super.clone();
    DeepProtoType deepProtoType = (DeepProtoType)deep;
    //对引用类型的属性,进行单独处理
    deepProtoType.deepcloneableTarget = (DeepCloneableTarget)deepCloneableTarget.clone();
    return deepProtoType;
    } //深拷贝-方式2通过对象的序列化实现(推荐)
    public 0bject deepClone() {
    //创建流对象
    ByteArrayOutputStream bos = null;
    ObjectOutputStream oos = null;
    ByteArrayInputStream bis = null;
    ObjectInputstream ois = null;
    try {
    //序列化
    bos = new ByteArrayOutputStream();
    oos = new ObjectOutputStream(bos);
    oos.writeobject(this); //当前这个对象以对象流的方式输出 //反序列化
    bis = new ByteArrayInputStream(bos.toByteArray());
    ois = new ObjectInputStream(bis);
    DeepPrototype copyObject = (DeepPrototype)ois.readObject();
    return copyObject;
    } catch(Exception e){
    e.printStackTrace();
    return null;
    } finally{
    try{
    bos.close();
    oos.close();
    bis.close();
    ois.close();
    } catch(Exception e2){
    e.printStackTrace();
    }
    }
    }
8 原型模式在Spring框架中应用

原型Bean的创建,就是原型模式的应用

9 注意事项
  • 创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率
  • 不用重新初始化对象,而是动态地获得对象运行时的状态
  • 如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化,无需修改代
  • 在实现深克隆的时候可能需要比较复杂的代码
  • 缺点:需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了ocp 原则。

03 原型模式(prototype)的更多相关文章

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

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

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

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

  3. 设计模式(四)原型模式Prototype(创建型)

      设计模式(四)原型模式Prototype(创建型) 1.   概述 我们都知道,创建型模式一般是用来创建一个新的对象,然后我们使用这个对象完成一些对象的操作,我们通过原型模式可以快速的创建一个对象 ...

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

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

  5. 原型模式-Prototype(Java实现)

    原型模式-Prototype 通过复制(克隆.拷贝)一个指定类型的对象来创建更多同类型的对象. 就像去蛋糕店买蛋糕一样. 柜台里的蛋糕都是非卖品. 只是为顾客提供一种参照. 当顾客看上某一个样式的蛋糕 ...

  6. 原型模式 prototype 创建型 设计模式(七)

    原型模式  prototype 意图 用原型实例指定需要创建的对象的类型,然后使用复制这个原型对象的方法创建出更多同类型的对象   显然,原型模式就是给出一个对象,然后克隆一个或者更多个对象 小时候看 ...

  7. PHP设计模式 原型模式(Prototype)

    定义 和工厂模式类似,用来创建对象.但实现机制不同,原型模式是先创建一个对象,采用clone的方式进行新对象的创建. 场景 大对象的创建. 优点 1.可以在运行时刻增加和删除产品 2.可以改变值或结构 ...

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

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

  9. 六个创建模式之原型模式(Prototype Pattern)

    定义: 使用原型实例指定创建对象的种类,并通过拷贝这个原型的属性创建新的对象. 结构图: Prototype:抽象原型类,声明克隆方法的接口,并是所有原型类的公共父类.在Java中,Object类为该 ...

随机推荐

  1. day25 Pyhton学习 MD5加密.日志

    一.MD5加密 MD5是一种不可逆的加密算法. 它是可靠的. 并且安全的. 在python中我们不需要手写这一套算法. 只需要引入一个叫hashlib的模块就能搞定MD5的加密工作 import ha ...

  2. python接口测试之读取配置文件

    1.python使用自带的configparser模块用来读取配置文件,配置文件可以为.conf或.ini结尾 在使用前需要先安装该模块,使用pip安装即可 2.新建一个名为a.conf的配置文件 a ...

  3. STM32中断

    STM32的中断分两个类型:内核异常和外部中断. 内核异常不能够被打断,不能被设置优先级(它的优先级是凌驾于外部中断之上的).常见的内核异常有以下几种:复位(reset),不可屏蔽中断(NMI),硬错 ...

  4. CentOS 6编译安装Redis

    [root@localhost ~]# vim /etc/sysconfig/iptables # 添加如下:-A INPUT -m state –state NEW -m tcp -p tcp –d ...

  5. T-sql语句,group by 加 order by的使用方法

    select AuHousesID,sum(Turnover) from Auction group by AuHousesID order by sum(Turnover) desc

  6. Helium文档6-WebUI自动化-S用于通过id\name\classname\xpth定位元素

    前言 S方法可以灵活定位元素特别注意,比如to_left_of参数的使用是查找在某个元素左侧的元素,但是默认只会找第一个S方法可以灵活运用,特别是没有id,没有name,只有classname的情况, ...

  7. linux 查看nginx的安装路径等信息

    做个随笔,记录一下. 想查看nginx的配置文件,但不知道nginx是安装在哪个目录下? ps -ef | grep nginx Linux在启动一个进程时,系统会在/proc下创建一个以PID命名的 ...

  8. eclipse快捷键(Mac版)整理

    eclipse快捷键(Mac版)整理 前言: 最近在学习JDBC,老师用的是eclipse,对于习惯了IDEA的我来说,没有了快捷键,效率明显下降. 我认为,开发工具的熟练使用,也是程序员必备的一项技 ...

  9. LeakCanary检测(二)

    在主方法主实现一个内存泄漏,检测到手机会发送通知,也可以用利用androidStudio自带的Profile检测内存泄漏 public class MainActivity extends AppCo ...

  10. 续 Eureka+Hystrix+Zuul(Zuul API网关)

    概述: 服务的合并,转发,验证,异构协议.将上百个请求融为一个发送到后台,返回大的JSON返回处理: 作用:这减少了客户端与应用程序间的交互次数,还简化了客户端代码. Zuul可以通过加载动态过滤机制 ...