详解Java的设计模式编程中的原型模式

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

原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件:
实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。
重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。
        原型模式是一种比较简单的模式,也非常容易理解,实现一个接口,重写一个方法即完成了原型模式。在实际应用中,原型模式很少单独出现。经常与其他模式混用,他的原型类Prototype也常用抽象类来替代。
实现代码:

package PrototypePattern;

public class PrototypeClass implements Cloneable{

 @Override
 protected PrototypeClass clone(){

  PrototypeClass prototypeClass = null;

  try {
   prototypeClass = (PrototypeClass)super.clone();
  } catch (CloneNotSupportedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

  return prototypeClass;
 }
}

客户端:

package PrototypePattern;

public class Client {
 public static void main(String[] args) {
  PrototypeClass obj1 = new PrototypeClass();
  PrototypeClass obj2 = obj1.clone();

  System.out.println(obj1);
  System.out.println(obj2);
 }
}

原型模式的优点及适用场景
       使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
       使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
       因为以上优点,所以在需要重复地创建相似对象时可以考虑使用原型模式。比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。

public class Prototype implements Cloneable {
 private ArrayList list = new ArrayList();
 public Prototype clone(){
  Prototype prototype = null;
  try{
   prototype = (Prototype)super.clone();
   prototype.list = (ArrayList) this.list.clone();
  }catch(CloneNotSupportedException e){
   e.printStackTrace();
  }
  return prototype;
 }
}


原型模式的注意事项:

  1. 构造函数不会被执行
  2. 浅拷贝和深拷贝
  3. clone和final的冲突

由于ArrayList不是基本类型,所以成员变量list,不会被拷贝,需要我们自己实现深拷贝,幸运的是java提供的大部分的容器类都实现了Cloneable接口。所以实现深拷贝并不是特别困难。
PS:深拷贝与浅拷贝问题中,会发生深拷贝的有java中的8中基本类型以及他们的封装类型,另外还有String类型。其余的都是浅拷贝。

(0)

相关推荐

  • Java设计模式之原型模式(Prototype模式)介绍

    Prototype模式定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建. 如何使用原型模式 因为Java中的提供clone()方法来实现对象的克隆,所以Prototype模式实现一下子变得很简单.以勺子为例: 复制代码 代码如下: public abstract cl

  • 讲解Java设计模式编程中的建造者模式与原型模式

    建造者模式 定义 又叫生成器模式,它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象. 当创建复杂对象的算法应该独立于该对象的组成部分时,而且构造过程必须允许被构造的对象有不同的表示时.我们可以考虑使用建造者模式. 实现 1. Builder为创建一个Product对象的各个部件指定抽象接口.通常包含创建产品和返回产品的抽象方法,也可以是具体方法,把创建过程放到ConcreteBuilder类中. 2. ConcreteBuilder 实

  • 设计模式之原型模式_动力节点Java学院整理

    定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. 类型:创建类模式 类图: 原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype.Prototype类需要具备以下两个条件: 实现Cloneable接口.在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法.在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedExcepti

  • 详解Java的设计模式编程中的原型模式

    定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. 类型:创建类模式 类图: 原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype.Prototype类需要具备以下两个条件: 实现Cloneable接口.在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法.在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedExcepti

  • 深入解析Java的设计模式编程中的模板方法模式

    定义:  定义一个操作中的算法的框架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤. 听起来好高端的样子,我的理解: 1.父类声明了若干个抽象方法(基本方法)和若干个具体方法(模板方法) 2.抽象方法是一个算法(过程)的步骤,在子类中实现 3.模板方法是一个算法(过程)的框架,在父类中已经约定好,实现对基本方法调用,完成固定的逻辑 4.一个算法(过程)的结构在父类中定义,具体的实现细节则在子类中实现 注:为了防止恶意操作,一般模板方法都加上final

  • 实例讲解Java的设计模式编程中责任链模式的运用

    定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止. 类型:行为类模式 类图: 首先来看一段代码: public void test(int i, Request request){ if(i==1){ Handler1.response(request); }else if(i == 2){ Handler2.response(request); }else if(i == 3){ Handler3

  • 详解C#的设计模式编程之抽象工厂模式的应用

    这里首先以一个生活中抽象工厂的例子来实现一个抽象工厂,然后再给出抽象工厂的定义和UML图来帮助大家更好地掌握抽象工厂模式,同时大家在理解的时候,可以对照抽象工厂生活中例子的实现和它的定义来加深抽象工厂的UML图理解.抽象工厂模式比其它工厂模式更加抽象,抽象工厂模式适用与多个抽象类的情况下,通过工厂返回多个抽象类中你需要得到的具体子类实例. 抽象工厂模式比其它工厂模式更加抽象,抽象工厂模式适用与多个抽象类的情况下,通过工厂返回多个抽象类中你需要得到的具体子类实例. 举例阐述抽象工厂模式: 假如中国

  • 详解Java图形化编程中的鼠标事件设计

    鼠标事件的事件源往往与容器相关,当鼠标进入容器.离开容器,或者在容器中单击鼠标.拖动鼠标时都会发生鼠标事件.java语言为处理鼠标事件提供两个接口:MouseListener,MouseMotionListener接口. MouseListener接口 MouseListener接口能处理5种鼠标事件:按下鼠标,释放鼠标,点击鼠标.鼠标进入.鼠标退出.相应的方法有: (1) getX():鼠标的X坐标 (2) getY():鼠标的Y坐标 (3) getModifiers():获取鼠标的左键或右键

  • 详解Java字节码编程之非常好用的javassist

    一.Javassist入门 (一)Javassist是什么 Javassist是可以动态编辑Java字节码的类库.它可以在Java程序运行时定义一个新的类,并加载到JVM中:还可以在JVM加载时修改一个类文件.Javassist使用户不必关心字节码相关的规范也是可以编辑类文件的. (二)Javassist核心API 在Javassist中每个需要编辑的class都对应一个CtCLass实例,CtClass的含义是编译时的类(compile time class),这些类会存储在Class Poo

  • 详解Java实现设计模式之责任链模式

    一.模拟业务需求 假设我们现在需要在我们的系统中导入一批关于学生信息的Excel的数据,其主要的信息有:学号.姓名.年龄.性别等等,在导入系统的时候,我们肯定不能直接的保存到数据库,我们肯定是先要对这个Excel的数据进行校验,看是否符合系统的要求,只有都符合了系统的要求了,我们把这些数据保存到数据库中去.假如我们的学生对应的实体类如下: @Data public class Student { /** * 学生编号 */ private String stNo; /** * 学生姓名 */ p

  • 详解Java分布式缓存系统中必须解决的四大问题

    目录 缓存穿透 缓存击穿 缓存雪崩 缓存一致性 分布式缓存系统是三高架构中不可或缺的部分,极大地提高了整个项目的并发量.响应速度,但它也带来了新的需要解决的问题,分别是: 缓存穿透.缓存击穿.缓存雪崩和缓存一致性问题. 缓存穿透 第一个比较大的问题就是缓存穿透.这个概念比较好理解,和命中率有关.如果命中率很低,那么压力就会集中在数据库持久层. 假如能找到相关数据,我们就可以把它缓存起来.但问题是,本次请求,在缓存和持久层都没有命中,这种情况就叫缓存的穿透. 举个例子,如上图,在一个登录系统中,有

  • 详解c++ atomic原子编程中的Memory Order

    概述 但是,基于内核对象的同步,会带来昂贵的上下文切换(用户态切换到内核态,占用1000个以上的cpu周期).就需要使用另一种方法 -- 原子指令. 仅靠原子技术实现不了对资源的访问控制,即使简单计数操作,看上去正确的代码也可能会crash. 这里的关键在于编译器和cpu实施的重排指令导致了读写顺序的变化.只要没有依赖,代码中在后面的指令就可能跑到前面去,编译器和CPU都会这么做. 注1:单线程代码不需要关心乱序的问题.因为乱序至少要保证这一原则:不能改变单线程程序的执行行为 注2:内核对象多线

  • 详解Java线程池队列中的延迟队列DelayQueue

    目录 DelayQueue延迟队列 DelayQueue使用场景 DelayQueue属性 DelayQueue构造方法 实现Delayed接口使用示例 DelayQueue总结 在阻塞队里中,除了对元素进行增加和删除外,我们可以把元素的删除做一个延迟的处理,即使用DelayQueue的方法.本文就来和大家聊聊Java线程池队列中的DelayQueue—延迟队列 public enum QueueTypeEnum { ARRAY_BLOCKING_QUEUE(1, "ArrayBlockingQ

随机推荐