05-Java原型模式 ( Prototype Pattern )

原型模式

    • 摘要
    • 实现
    • 范例

  • 原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能
  • 原型模式实现了一个原型接口,该接口用于创建当前对象的克隆
  • 当直接创建对象的代价比较大时,则采用这种模式
    例如,一个对象需要在一个高代价的数据库操作之后被创建

我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用
原型模式属于创建型模式,它提供了一种创建对象的最佳方式

摘要

1. 意图

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

2. 主要解决

在运行期建立和删除原型

3. 何时使用

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

4. 如何解决

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

5. 关键代码

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

6. 应用实例

  • 细胞分裂;
  • JAVA中的Objectclone()方法;

7. 优点

  • 性能提高;
  • 逃避构造函数的约束;

8. 缺点

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

9. 使用场景

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

原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用

10. 注意事项

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

实现

在这里插入图片描述

  1. 创建一个抽象类Shape和扩展了Shape类的实体类;
  2. 定义类ShapeCache,该类把shape对象存储在一个Hashtable中,并在请求的时候返回它们的克隆;
  3. PrototypPatternDemo类使用ShapeCache类来获取Shape对象;

范例

1. 创建一个实现了 Clonable 接口的抽象类 Shape.

Shape.java

package com.demo.gof;
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

package com.demo.gof;
public class Rectangle extends Shape {

   public Rectangle(){
     type = "Rectangle";
   }

   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

Square .java

package com.demo.gof;
public class Square extends Shape {

   public Square(){
     type = "Square";
   }

   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

Circle.java

package com.demo.gof;
public class Circle extends Shape{

   public Circle(){
     type = "Circle";
   }

   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}

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

ShapeCache .java

package com.demo.gof;
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

package com.demo.gof;
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());      
   }
}

编译运行以上 Java 范例,输出结果如下

$ javac -d . src/main/com.demo/gof/PrototypePatternDemo.java
$ java  com.demo.gof.PrototypePatternDemo
Shape : Circle
Shape : Square
Shape : Rectangle

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HiveQL——不借助任何外表,产生连续数值

注&#xff1a;参考文章&#xff1a; HiveSql一天一个小技巧&#xff1a;如何不借助其他任何外表&#xff0c;产生连续数值_hive生成连续数字-CSDN博客文章浏览阅读1.3k次。0 需求描述输出结果如下所示&#xff1a;12345...1001 问题分析方法一&#xff1a;起始值&#xff08;…

fast.ai 深度学习笔记(七)

深度学习 2&#xff1a;第 2 部分第 14 课 原文&#xff1a;medium.com/hiromi_suenaga/deep-learning-2-part-2-lesson-14-e0d23c7a0add 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 来自 fast.ai 课程的个人笔记。随着我继续复习课程以“真正”理解它&#xff0c;…

洗地机买什么品牌好?最好的洗地机品牌

对于双职工家庭来说&#xff0c;日常家务活是一个很大的难题。所以就要借助洗地机来提升生活质量&#xff0c;确实智能家电能够帮助日常家务减负。市面上的洗地机的品牌是真的很多&#xff0c;笔者今天带大家一起来看看什么洗地机品牌好用。 该如何挑选适合自己的家用洗地机 …

算法学习——LeetCode力扣栈与队列篇2

算法学习——LeetCode力扣栈与队列篇2 150. 逆波兰表达式求值 150. 逆波兰表达式求值 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个字符串数组 tokens &#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。…

六、滚动条操作——调整图像亮度

亮度调整&#xff1a;在原来的图像基础上&#xff0c;对每个像素点值增加或减小&#xff0c;是图片整体亮度的增加或降低 项目最终效果&#xff1a;通过滚动条trackbar来实现调整图片亮度和对比度的功能 我这里创建的项目为&#xff1a;track_bar_light 一、创建滚动条调整图…

Spring基础 - SpringMVC请求流程和案例

Spring基础 - SpringMVC请求流程和案例 什么是MVC 用一种业务逻辑、数据、界面显示分离的方法&#xff0c;将业务逻辑聚集到一个部件里面&#xff0c;在改进和个性化定制界面及用户交互的同时&#xff0c;不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理…

电商小程序06用户审核

目录 1 创建自定义应用2 显示待办数量3 创建审核页面4 开发审核功能5 搭建布局6 最终效果总结 上一篇我们讲解了用户注册的功能&#xff0c;用户注册之后状态是待审核&#xff0c;需要管理员进行审核。通常给管理员提供一套PC端的软件进行相关的操作&#xff0c;在低代码中&…

离线数仓(一)【数仓概念、需求架构】

前言 今天开始学习数仓的内容&#xff0c;之前花费一年半的时间已经学完了 Hadoop、Hive、Zookeeper、Spark、HBase、Flume、Sqoop、Kafka、Flink 等基础组件。把学过的内容用到实践这是最重要的&#xff0c;相信会有很大的收获。 1、数据仓库概念 1.1、概念 数据仓库&#x…

【MySQL】数据库的基础——数据库的介绍、MySQL的介绍和架构、SQL分类、MySQL的基本使用、MySQL的存储引擎

文章目录 MySQL1. 数据库的介绍1.2 主流数据库 2. MySQL的介绍2.1 MySQL架构2.2 SQL分类2.3 MySQL的基本使用2.4 MySQL存储引擎 MySQL 1. 数据库的介绍 数据库&#xff08;Database&#xff0c;简称DB&#xff09;是按照数据结构来组织、存储和管理数据的仓库。它是长期存储在计…

中年低端中产程序员从西安出发到海南三亚低成本吃喝万里行:西安-南宁-湛江-雷州-徐闻-博鳌-陵水-三亚-重庆-西安

文章大纲 旅途规划来回行程的确定南宁 - 北海 - 湛江轮渡成为了最终最大的不确定性&#xff01;感谢神州租车气温与游玩地点总体花费 游玩过程出发时间&#xff1a;Day1-1月25日星期四&#xff0c;西安飞南宁路途中&#xff1a;Day2-1月26日星期五&#xff0c;南宁-湛江-住雷州…

数据分析基础之《pandas(7)—高级处理2》

四、合并 如果数据由多张表组成&#xff0c;那么有时候需要将不同的内容合并在一起分析 1、先回忆下numpy中如何合并 水平拼接 np.hstack() 竖直拼接 np.vstack() 两个都能实现 np.concatenate((a, b), axis) 2、pd.concat([data1, data2], axis1) 按照行或者列…

第二节 zookeeper基础应用与实战

目录 1. Zookeeper命令操作 1.1 Zookeeper 数据模型 1.2 Zookeeper服务端常用命令 1.3 Zookeeper客户端常用命令 1.3.1 基本CRUD 1.3.2 创建临时&顺序节点 2. Zookeeper JavaAPI操作 2.1 Curator介绍 2.2 引入Curator 2.3 建立连接 2.4 添加节点 2.5 修改节点 …

一周学会Django5 Python Web开发-Django5创建项目(用PyCharm工具)

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计11条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述(10)

接前一篇文章&#xff1a;《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述&#xff08;9&#xff09; 4.2 PCIe体系结构的组成部件 PCIe总线作为处理器系统的局部总线&#xff0c;其作用与PCI总线类似&#xff0c;主要目的是为了连接处理器系统中的外部设备&…

C语言中的数据类型-强转

强制类型转换 概念&#xff1a;将某种类型的数据转化我们需要的数据类型&#xff0c;注意强制类型转化是临时强转&#xff0c;不会改变本身的数据类型。 强转又分为显式强转和隐式转化 显示强转是按照我们的要求进行转化 格式&#xff1a;(需要转化数据类型)变量名 #inclu…

C#,欧拉常数(Euler Constant)的算法与源代码

1 欧拉常数 欧拉常数最先由瑞士数学家莱昂哈德 欧拉 (Leonhard Euler) 在1735年发表的文章《De Progressionibus harmonicus observationes》中定义。欧拉曾经使用γ作为它的符号&#xff0c;并计算出了它的前6位&#xff0c;1761年他又将该值计算到了16位 。 欧拉常数最先由瑞…

Swift 使用 Combine 进行开发 从入门到精通七

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二Swift Combine 管道 从入门到精通三Swift Combine 发布者publisher的生命周期 从入门到精通四Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五Swift Com…

Dubbo源码一:【Dubbo与Spring整合】

正常在项目中&#xff0c;我们都是在Spring环境下使用Dubbo&#xff0c;所以我们这里就在Spring的环境下看看Dubbo是如何运作的 入口 在源码下载下来之后&#xff0c;有一个dubbo-demo目录&#xff0c;里面有一个基于spring注解的子目录dubbo-demo-annotation, 里面有一个生产…

蓝桥杯每日一题------背包问题(二)

前言 本次讲解背包问题的一些延申问题&#xff0c;新的知识点主要涉及到二进制优化&#xff0c;单调队列优化DP&#xff0c;树形DP等。 多重背包 原始做法 多重背包的题意处在01背包和完全背包之间&#xff0c;因为对于每一个物品它规定了可选的个数&#xff0c;那么可以考虑…

M1 Mac使用SquareLine-Studio进行LVGL开发

背景 使用Gui-Guider开发遇到一些问题&#xff0c;比如组件不全。使用LVGL官方的设计软件开发 延续上一篇使用的基本环境。 LVGL项目 新建项目 选择Arduino的项目&#xff0c;设定好分辨率及颜色。 设计UI 导出代码 Export -> Create Template Project 导出文件如图…