创造性模式——原型模式

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用

一、介绍

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

适用场景:

  1. 当一个系统应该独立于它的产品创建,构成和表示时。
  2. 当要实例化的类是在运行时刻指定时,例如,通过动态装载。
  3. 为了避免创建一个与产品类层次平行的工厂类层次时。
  4. 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

实现方式:利用已有的一个原型对象,快速地生成和原型对象一样的实例。

  1. 实现克隆操作,在 JAVA 继承 Cloneable,重写 clone(),在 .NET 中可以使用 Object 类的 MemberwiseClone() 方法来实现对象的浅拷贝或通过序列化的方式来实现深拷贝。
  2. 原型模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些"易变类"拥有稳定的接口。

优点:

  1. 性能提高。
  2. 逃避构造函数的约束。

缺点:

  1. 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
  2. 必须实现 Cloneable 接口。

使用场景范例:

  1. 资源优化场景。
  2. 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
  3. 性能和安全要求的场景。
  4. 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
  5. 一个对象多个修改者的场景。
  6. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
  7. 在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用。

PS:与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。

二、范例

我们将创建一个抽象类 Shape 和扩展了 Shape 类的实体类。下一步是定义类 ShapeCache,该类把 shape 对象存储在一个 Hashtable 中,并在请求的时候返回它们的克隆。

PrototypePatternDemo 类使用 ShapeCache 类来获取 Shape 对象。

原型模式的 UML 图

步骤 1

创建一个实现了 Cloneable 接口的抽象类。

Shape.java

public abstract class Shape implements Cloneable {private String id;protected String type;abstract void draw();public String getType() {return type;}public String getId() {return id;}public void setId(String id) {this.id = id;}public Object clone() {Object clone = null;try {clone = super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return clone;}
}

步骤 2

创建扩展了上面抽象类的实体类。

Rectangle.java

public class Rectangle extends Shape {public Rectangle() {type = "Rectangle";}@Overridepublic void draw() {System.out.println("Inside Rectangle::draw() method.");}
}

Square.java

public class Square extends Shape {public Square() {type = "Square";}@Overridepublic void draw() {System.out.println("Inside Square::draw() method.");}
}

Circle.java

public class Circle extends Shape {public Circle() {type = "Circle";}@Overridepublic void draw() {System.out.println("Inside Circle::draw() method.");}
}

步骤 3

创建一个类,从数据库获取实体类,并把它们存储在一个 Hashtable 中。

ShapeCache.java

import java.util.Hashtable;public class ShapeCache {private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>();public static Shape getShape(String shapeId) {Shape cachedShape = shapeMap.get(shapeId);return (Shape) cachedShape.clone();}// 对每种形状都运行数据库查询,并创建该形状// shapeMap.put(shapeKey, shape);// 例如,我们要添加三种形状public static void loadCache() {Circle circle = new Circle();circle.setId("1");shapeMap.put(circle.getId(), circle);Square square = new Square();square.setId("2");shapeMap.put(square.getId(), square);Rectangle rectangle = new Rectangle();rectangle.setId("3");shapeMap.put(rectangle.getId(), rectangle);}
}

步骤 4

PrototypePatternDemo 使用 ShapeCache 类来获取存储在 Hashtable 中的形状的克隆。

PrototypePatternDemo.java

public class PrototypePatternDemo {public static void main(String[] args) {ShapeCache.loadCache();Shape clonedShape = (Shape) ShapeCache.getShape("1");System.out.println("Shape : " + clonedShape.getType());Shape clonedShape2 = (Shape) ShapeCache.getShape("2");System.out.println("Shape : " + clonedShape2.getType());Shape clonedShape3 = (Shape) ShapeCache.getShape("3");System.out.println("Shape : " + clonedShape3.getType());}
}

步骤 5

执行程序,输出结果:

Shape : Circle
Shape : Square
Shape : Rectangle

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/535544.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java集合:关于 LinkedList 的内容盘点

本篇内容包括&#xff1a;LinkedList 的概述、LinkedList 的结构既双向链表实现与LinkedList-Node 结构、LinkedList 的使用&#xff08;构造方法&常用方法&#xff09;、关于 Queue 队列的介绍、关于 ArrayList 和 LinkedList 的区别以及算法&#xff1a;翻转链表&#xf…

oracle迁移父子数据

现有需求如下&#xff0c;业务组织单元表中id字段数据在另外一个系统全部重复&#xff0c;但需要将此业务单元组织导入另一系统 业务组织单元表Isc_Specialorg_Unit 表中存在ID字段为子节点数据&#xff0c;parent_id为父节点数据&#xff0c;orgpath为组织路径 现在做如下操…

oracle表空间

概念 表空间和数据文件 ●表空间是逻辑存储概念&#xff0c;一个表空间是一个或多个数据文件的逻辑集合 ●存储对象(表、索引)逻辑的存储在表空间上&#xff0c;而存储对象的数据物理的存放在数据文件上 ●数据库至少需要一个叫做system的表空间&#xff0c;也就是系统表空间 ●…

oracle日志

日志分类 redo log files联机日志或重做日志 archived log files归档日志 1184198alert log files 告警日志 trace files user_ _dump_ _dest 用户信息日志如跟踪会话日志 background dump_ dest进程日志还有其他一-些不常用的日志 v$database的log_mode 数据库归档模式…

MySQL:分库分表知识点盘点

本篇内容包括&#xff1a;数据库瓶颈、分库分表以及分库分表相关问题 一、数据库瓶颈 不管是IO瓶颈&#xff0c;还是CPU瓶颈&#xff0c;最终都会导致数据库的活跃连接数增加&#xff0c;进而逼近甚至达到数据库可承载活跃连接数的阈值。在业务Service来看就是&#xff0c;可用…

oracle的sga

sga SGA的管理 ■有三种方式&#xff1a; ●8i:SGA的总大小由所有内存组件大小之和决定&#xff0c;不能直接定义SCA大小。对内部组件大小的修改必须在数据库重起 后 才能生为&#xff0c;所以叫做SGA的静态管理。 ●9i&#xff…

MySQL:主从相关知识点盘点

本篇内容包括&#xff1a;MySQL 主从复制简介、主从复制的原理以及主从搭建 一、MySQL 主从复制简介 在实际的生产中&#xff0c;为了解决Mysql的单点故障已经提高MySQL的整体服务性能&#xff0c;一般都会采用**「主从复制」**。 比如&#xff1a;在复杂的业务系统中&#x…

oracle导出expdp

expdp/impdp 是 oracle 10g 版本后推出的服务器端工具--数据泵&#xff0c;作用是为了将数据库中的逻辑对象&#xff0c;比如表、用户、全库、表空间进 行导入&#xff0c;导出 命令解析 ATTACH ATTACH [[schema_name.]job_name] schema_name 表示用户名,job_name 表示导出的作…

oracle检查点

检 查 点 概述 ■l当修改数据时&#xff0c;需要首先将数据读入内存中&#xff08;Buffer Cache&#xff09;&#xff0c;修改数据的同时&#xff0c;Oracle会记录重做信息&#xff08;Redo&#xff09;用于恢复。因 为有了重做信息的存在&#xff0c;Oracle不需要在提交时…

文献翻译:Java theory and practice: Fixing the Java Memory Model, Part 2

Java theory and practice: Fixing the Java Memory Model, Part 2 译&#xff1a;Java 理论与实践&#xff1a;修复 Java 内存模型&#xff0c;第 2 部分 翻译自&#xff1a;http://www.ibm.com/developerworks/library/j-jtp03304/&#xff08;原文写于2004年3月&#xff0…

常用系统函数oracle

单行函数日期函数ADD_MONTHS(date, n):用于从一个日期值增加或减少一些月份 MONTHS_BETWEEN(date1, date2):判断两个日期之间相差的月份 LAST_DAY(date): 函数返回包含日期的月份的最后一天 ROUND(date[,fmt]): 将日期d按照fmt指定的格式舍入&#xff0c;fmt为字符串 TRU…

oracle游标

游标&#xff08;cursor &#xff09;是一个私有的SQL工作区域,是一个指向上下文区的句柄或指针&#xff0c;位于内存中的 "临时表"。 游标是SQL的一个内存工作区&#xff0c;由系统或用户以变量的形式定义。游标的作用就是用于临时存储从数据库中提取的数据块。在某…

系统学习SpringFramework:Spring IOC

本篇内容包括&#xff1a;IOC 和 DI 的概念、Spring 容器&#xff0c;即 BenaFactory 与 AplicationConext 等 IOC 相关内容。 一、IOC 和 DI 的概念 1、IOC IoC&#xff08;Inversion of control &#xff09;即“控制反转”&#xff0c;它是一种设计思想而非一个技术实现。…

rowid

ROWID的格式rowidOOOOOOFFFBBBBBBRRR说明数据对象号相对文件号数据块号行号 上述表格是Oracle 9i及以上版本数据库中的rowid格式: 6位对象号3位相对文件号6位数据块号3位行号&#xff0c;是一个18位的64进制值。这个18位的64进制值在数据库内却是以10个bytes合计80个bit的二进制…

系统学习SpringFramework:循环依赖与三级缓存

本篇内容包括&#xff1a;Spring 中的循环依赖问题&#xff08;包括 Spring 中的循环依赖问题和Spring 中的循环依赖的 5 种场景的介绍&#xff09;、Spring 三级缓存介绍、4 个 Spring 无法自动解决的循环以来场景以及其对应的手动解决方式。 一、Spring 中的循环依赖问题 1、…

深入理解Java虚拟机:Java类的加载机制

本篇内容包括&#xff1a;Java 类的加载机制&#xff08;Jvm 结构组成、Java 类的加载&#xff09;、类的生命周期&#xff08;加载-验证-准备-解析-初始化-使用-卸载&#xff09;、类加载器 以及 双亲委派模型。 一、Java 类的加载机制 1、 Jvm 结构组成 Jvm 整体组成可分为…

新版谷歌浏览器开启Flash支持

浏览器地址栏中输入chrome://version查看Chrome浏览器、Flash插件的版本信息。 Chrome 69.0-70.0版本Chrome 71.0-74.0及以后版本谷歌浏览器地址栏中输入【chrome://flags/#enable-ephemeral-flash-permission】&#xff0c;将【Enable Ephemeral Flash Permissions】从【Defau…

深入理解Java虚拟机:Java垃圾回收机制

本篇内容包括&#xff1a;JAVA 垃圾回收机制概述、有哪些内存需要回收、如何回收&#xff08;标记-清除、标记-整理&#xff08;标记-清除-压缩&#xff09;、复制&#xff08;标记-复制-清除&#xff09;、分代收集等算法&#xff09; 以及 何时进行垃圾回收等内容&#xff01…

深入理解Java虚拟机:Java垃圾回收器

本篇内容包括&#xff1a;7 种 Jvm 垃圾回收器的介绍、对比 以及 对应的 Jvm 参数设置&#xff0c;这 7 种包括了&#xff1a;Serial、ParNew 以及 Parallel Scavenge 三种新生代回收器 和 &#xff1a;Serial Old、Parallel Old 以及 CMS 三种老年代回收器&#xff0c;此外还有…

网络协议:什么是网络分层的七四五

本篇内容包括&#xff1a;网络分层七层、五层、四层网络协议概念的介绍&#xff0c;IOS 体系结构的介绍与构成、TCP/IP体系结构的简介及与IOS体系的关系 以及五层体系结构的介绍。 一、七层、五层、四层网络协议概念 1、关于网络协议 网络协议&#xff0c;即是指计算机网络中…