java设计模式学习之【享元模式】

news2024/9/22 23:39:30

文章目录

  • 引言
  • 享元模式简介
    • 定义与用途
    • 实现方式
  • 使用场景
  • 优势与劣势
  • 在Java中的应用
  • 享元模式在Spring中的应用
  • 画图示例
  • 代码地址

引言

想象一下,您正在开发一个游戏,游戏中有成千上万的树木和建筑。如果每个对象都独立存储它的所有数据,将会占用大量的内存资源。享元模式提供了一种优化的解决方案,它通过共享相似对象的共有部分,减少内存的使用,同时保持独立对象的特性。

享元模式简介

定义与用途

享元模式(Flyweight Pattern)是一种结构型设计模式,用于减少创建大量相似对象的内存开销。它通过共享相似对象的共有状态,减少资源消耗,特别是在需要大量对象的情况下。

实现方式

实现享元模式通常包括以下几个关键组件:

  • 享元接口(Flyweight): 定义了享元对象的共有方法。
  • 具体享元(Concrete Flyweight): 实现享元接口,存储内部状态。
  • 享元工厂(Flyweight Factory): 创建并管理享元对象,确保合理地共享对象。

使用场景

享元模式适用于以下场景:

  • 当一个应用程序需要大量的相似对象时,可以使用享元模式来减少内存消耗。
  • 当对象的大多数状态可以被外部化时,享元模式可以有效地共享数据。
  • 当需要细粒度对象来表示数据时,而且这些数据可以被共享。

例如:

  1. 游戏开发中的环境设计:如树木、草、石头等,可以共享相同的模型和纹理。
  2. 文本处理程序中的字符处理:字符实例可以被共享,以减少内存占用。
  3. 用户界面中的控件和图标:在整个应用中可以共享相同的图标或控件实例。

优势与劣势

  • 优势
    减少内存消耗: 通过共享相似对象,显著减少内存占用。
    提高性能: 减少对象创建和销毁的开销,提升应用性能。
  • 劣势
    增加系统复杂性: 需要维护共享对象的状态,可能增加系统的复杂性。
    外部状态管理: 享元对象的外部状态需要由客户端代码维护,可能增加客户端的负担。

在Java中的应用

在Java中,String常量池是享元模式的一个经典例子。Java虚拟机(JVM)中的String常量池存储了所有的字符串字面量。这些字符串字面量是共享的,从而节约了内存。

享元模式在Spring中的应用

在Spring框架中,享元模式的应用并不像一些其他设计模式那样显而易见,但它确实在一些关键部分发挥作用,特别是在优化性能和资源管理方面。以下是一些示例:

Spring Bean的作用域管理:在Spring框架中,Bean的作用域可以被定义为单例(Singleton),这实际上是享元模式的一种应用。在单例模式下,Spring容器为每个Bean定义创建一个唯一的实例,并在整个容器中共享这个实例。这种方式减少了对象的创建,从而节约资源和提高效率。

Spring Security的权限缓存:在Spring Security中,权限信息经常被缓存以提高性能。这些权限对象的实例在需要时被创建,并在多个上下文中共享,这就是一种享元模式的实现。通过共享相同的权限对象实例,Spring Security减少了对象的创建和内存占用。

资源池的实现:在Spring中,资源如数据库连接和线程池常常使用享元模式进行管理。这些资源被创建并存储在池中,当需要时可以被多个客户端共享和重用。这样的资源共享减少了资源的频繁创建和销毁,优化了性能。

缓存机制:Spring框架提供了缓存抽象,可以通过缓存共享经常访问的数据,减少对外部系统(如数据库)的访问。这种缓存策略的背后思想与享元模式相似,即重用已有对象来减少资源消耗和提高效率。

通过这些应用,Spring框架有效地实现了享元模式的核心思想:共享和重用对象,以减少资源消耗和提高应用性能。

画图示例

在这里插入图片描述
步骤 1: 创建图形一个接口。

public interface Shape {
    void draw();
}

步骤 2: 实现具体类,创建了 Circle 类,实现了 Shape 接口。这个类包含圆的属性,如颜色、坐标和半径。

public class Circle implements Shape {
   private String color;
   private int x;
   private int y;
   private int radius;

   public Circle(String color){
      this.color = color;		
   }

   // 省略了设置 x, y, radius 的方法

   @Override
   public void draw() {
      System.out.println("绘制圆形:[颜色 : " + color + ", x : " + x + ", y :" + y + ", 半径 :" + radius);
   }
}

步骤 3: 创建工厂类
ShapeFactory 类用于基于给定的信息(如颜色)生成 Circle 对象。它内部维护了一个 HashMap,用于缓存已经创建的 Circle 对象。

import java.util.HashMap;

public class ShapeFactory {

   private static final HashMap<String, Circle> circleMap = new HashMap<>();

   public static Shape getCircle(String color) {
      Circle circle = circleMap.get(color);

      if(circle == null) {
         circle = new Circle(color);
         circleMap.put(color, circle);
         System.out.println("创建颜色为 " + color + " 的圆形");
      }
      return circle;
   }
}

步骤 4: 使用工厂类
FlyweightPatternDemo 类演示了如何使用 ShapeFactory 来获取特定颜色的 Circle 实例。它演示了如何有效地重用已经创建的对象,而不是每次都创建新对象。

public class FlyweightPatternDemo {
   private static final String[] colors = { "红色", "绿色", "蓝色", "白色", "黑色" };

   public static void main(String[] args) {
      for(int i = 0; i < 20; ++i) {
         Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor());
         circle.setX(getRandomX());
         circle.setY(getRandomY());
         circle.setRadius(100);
         circle.draw();
      }
   }

   private static String getRandomColor() {
      return colors[(int)(Math.random() * colors.length)];
   }

   private static int getRandomX() {
      return (int)(Math.random() * 100);
   }

   private static int getRandomY() {
      return (int)(Math.random() * 100);
   }
}

在这里插入图片描述
这个示例中,ShapeFactory 充当享元工厂,管理 Circle 对象的创建和缓存。当请求特定颜色的圆时,工厂首先检查是否已经创建了该颜色的圆。如果已存在,则重用该对象;如果不存在,才创建新的圆,并将其存储在哈希表中以供将来重用。这种方式显著减少了对象创建的数量,从而优化了内存使用和性能。

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern

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

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

相关文章

前端路由钩子的神奇之处:你真的了解它们吗?(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

JAVAEE大型金融支付-第1章-讲义-项目介绍

第1章 讲义-项目介绍与环境搭建 1.项目背景 1.1 项目背景 随着移动支付的盛行&#xff0c;商业银行、第三方支付公司、其它清算机构、消费金融公司等众多类型的机构&#xff0c;都在为商户 提供网络&#xff08;移动&#xff09;支付解决方案。另一方面&#xff0c;用户的支…

狗dog目标检测数据集VOC+YOLO格式1W+张

狗&#xff0c;是食肉目犬科 [11]犬属 [13]哺乳动物 [12]&#xff0c;别称犬&#xff0c;与马、牛、羊、猪、鸡并称“六畜” [13]。狗的体型大小、毛色因品种不同而不同&#xff0c;体格匀称&#xff1b;鼻吻部较长&#xff1b;眼呈卵圆形&#xff1b;两耳或竖或垂&#xff1b;…

RTX 40 SUPER发布时间定了!价格也有了

快科技12月16日消息&#xff0c;NVIDIA RTX 40 SUPER系列显卡基本确定将在2024年1月8日正式发布&#xff0c;也就是CES 2024大展期间&#xff0c;随后在1月中下旬陆续解禁上市。 RTX 4070 SUPER 1月16日解禁公版/原价丐版&#xff0c;1月17日解禁高价高配版&#xff0c;上市开…

高云GW1NSR-4C开发板M3核串口通信

1.PLLVR频率计算 高云的M3核要用到PLLVR核&#xff0c;其输出频率FCLKIN*(FBDIV_SEL1)/(IDIV_SEL1)&#xff0c;但同时要满足FCLKIN*(FBDIV_SEL1)*ODIV_SEL)/(IDIV_SEL1)的值在600MHz和1200MHz之间。例如官方示例&#xff0c;其输入频率FCLKIN50MHz&#xff0c;要输出80MHz&am…

5个创建在线帮助文档的好方法!

在线帮助文档是企业为用户提供支持服务的重要工具&#xff0c;它能够帮助用户更好地了解和使用产品&#xff0c;提高用户体验。然而&#xff0c;创建一份优秀的在线帮助文档需要掌握一定的技巧和方法。接下来就介绍一下创建在线帮助文档的5个好方法&#xff0c;帮助企业更好地为…

【C++干货铺】会搜索的二叉树(BSTree)

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 前言&#xff1a; 二叉搜索树 二叉搜索树概念 二叉搜索树操作 二叉搜索树的查找 二叉搜索树的插入 二叉搜索树元素的删除 ​二叉搜索树的实现 BSTree结点 …

C#学习笔记 - C#基础知识 - C#从入门到放弃

C# 持续更新中~~ 上次更新日期&#xff1a;20231215 第1节 C# 简单介绍1.1 C# 是什么1.2 C# 强大的编程功能1.3 C# 发展史1.4 C#与Java区别 第2节 C#基本语法2.1 C#程序结构2.2 C# 结构解析2.3 命名空间及标识符、关键字2.3.1 别名的使用2.3.2 标识符2.3.3 C#关键字 第3节 变量…

树莓派(Raspberry Pi)4B密码忘记了,怎么办?

树莓派长时间不用&#xff0c;导致密码忘记了&#xff0c;这可咋整&#xff1f; 第1步&#xff1a;取出SD卡 将树莓派关机&#xff0c;移除sd卡&#xff0c;使用读卡器&#xff0c;插入到你的电脑。 第2步&#xff1a;编辑 cmdline.txt 在PC上打开SD卡根目录&#xff0c;启动…

windows电脑半夜突然睡眠自动唤醒的问题查找与治理

遇见几次了&#xff0c;半夜起来上厕所&#xff0c;发现休眠的电脑居然自己开了&#xff0c;还得跑过去把电脑再休眠&#xff0c;很烦。昨天晚上居然自动唤醒两次&#xff0c;忍无可忍了&#xff0c;于是开始查找原因。 查询原因如下&#xff0c;解决方面也在后面。 固件 S3 计…

电子元器件-电阻

电阻 采样限流定时保护上拉 链接: 另类方式讲电阻&#xff01; 采样 应用场景&#xff0c;如我们在调节汽车座椅的过程中&#xff0c;如果座椅的行程达到尽头&#xff0c;此时控制座椅运动的电机就会停止&#xff0c;因而导致电机的电流非常大。如果正常运转的电流为1A&#…

大家都崩,美团不崩:其高可用架构,巧夺天工!

说在前面 在40岁老架构师尼恩的50读者群中&#xff0c;一直在指导大家简历&#xff0c;指导大家职业升级。 前几天&#xff0c;指导了一个40岁老伙伴拿到年薪100W offer&#xff0c;小伙伴的优势在异地多活。 在简历指导的过程中&#xff0c;尼恩发现&#xff1a; 异地多活的…

alibaba druid连接池

alibaba druid连接池 如果是SpringBoot 3.x&#xff0c;使用以下依赖 com.alibaba druid-spring-boot-3-starter ${druid-spring-boot-starter.version} application.yml配置 登录页面配置 切面监控springboot类 对 Web 请求的监控 配置filter&#xff0c;收集统计信息&#x…

DevEco Studio中配置代码片段

进入设置&#xff08;快捷键CtrlAltS&#xff09; 选择Editor > Live Templates 添加片段 其中 $END$ 代表光标首次出现位置 一定要选择适用语言&#xff01;&#xff01;&#xff01; 最后Apply > OK 即可&#xff0c;输入快捷命令回车即可快速生成代码片段。

权重衰减(Weight Decay)

在深度学习中&#xff0c;权重衰减&#xff08;Weight Decay&#xff09;是一种常用的正则化技术&#xff0c;旨在减少模型的过拟合现象。权重衰减通过向损失函数添加一个正则化项&#xff0c;以惩罚模型中较大的权重值。 一、权重衰减 在深度学习中&#xff0c;模型的训练过程…

Flutter在Visual Studio Code上首次创建运行应用

一、创建Flutter应用 1、前提条件 安装Visual Studio Code并配置好运行环境 2、开始创建Flutter应用 1)、打开Visual Studio Code 2)、打开 View > Command Palette。 3)、在搜索框中输入“flutter”&#xff0c;弹出内容如下图所示&#xff0c;选择“ Flutter: New Pr…

SoloLinker第一次使用记录,解决新手拿到板子的无所适从

本文目录 一、简介二、进群获取资料2.1 需要下载资料2.2 SDK 包解压 三、SDK 编译3.1 依赖安装3.2 编译配置3.3 启动编译3.4 编译后的固件目录 四、固件烧录4.1 RV1106 驱动安装4.2 打开烧录工具4.3 进入boot 模式&#xff08;烧录模式&#xff09;4.4 烧录启动固件4.5 烧录升级…

浏览器录屏技术探究与实践

一、引言 随着网络技术的快速发展&#xff0c;浏览器已经成为人们获取信息的主要途径。浏览器录屏技术作为一种新兴的媒体捕捉和分享方式&#xff0c;逐渐受到广泛关注。本文将对浏览器录屏技术进行深入探讨&#xff0c;分析其实现原理&#xff0c;并给出实际应用中的解决方案…

MC-30A (32.768 kHz用于汽车应用的晶体单元)

MC-30A 32.768 kHz用于汽车应用的晶体&#xff0c;车规晶振中的热销型号之一。该款石英晶体谐振器&#xff0c;可以在-40 to 85 C的温度内稳定工作&#xff0c;能满足起动振动的要求。同时满足AEC-Q200无源元件质量标准认证&#xff0c;满足汽车仪表系统的所有要求。 频率范围…

内网穿透工具,如何保障安全远程访问?

内网穿透工具是一种常见的技术手段&#xff0c;用于在没有公网IP的情况下将本地局域网服务映射至外网。这种工具的使用极大地方便了开发人员和网络管理员&#xff0c;使得他们能够快速建立起本地服务与外部网络之间的通信渠道。然而&#xff0c;在享受高效快捷的同时&#xff0…