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

文章目录

  • 引言
  • 享元模式简介
    • 定义与用途
    • 实现方式
  • 使用场景
  • 优势与劣势
  • 在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

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

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

相关文章

postman接口测试系列: 时间戳和加密

在使用postman进行接口测试的时候&#xff0c;对于有些接口字段需要时间戳加密&#xff0c;这个时候我们就遇到2个问题&#xff0c;其一是接口中的时间戳如何得到&#xff1f;其二就是对于现在常用的md5加密操作如何在postman中使用代码实现呢&#xff1f; 下面我们以一个具体的…

蚂蚁SEO实用的网络baidu蜘蛛有哪些

网络蜘蛛是一种用于从互联网上自动抓取信息的程序。它们根据给定的规则和指令&#xff0c;遍历网站上的页面&#xff0c;收集信息并将其存储在数据库中。网络蜘蛛在搜索引擎、数据挖掘、信息提取等领域有着广泛的应用。本文将介绍一种实用的网络蜘蛛&#xff0c;并探讨其实现原…

快速二维相位解包算法基于按照非连续路径进行可靠性排序

Miguel Arevallilo Herra ez, David R. Burton, Michael J. Lalor, and Munther A. Gdeisat 摘要&#xff1a; 据我们所知&#xff0c;我们描述了一种新的相位展开技术。已经提出了几种基于首先展开最可靠像素的算法。这些仅限于连续路径&#xff0c;并且在定义起始像素时会遇…

结合eNSP实验讲VLAN,让理论生动

目录 一、VLAN的简介 1、定义 2、产生的原因--解决传统以太网的问题 3、VLAN的作用 4、VLAN数据帧格式--插入VLAN标签 5、VLAN的种类 5.1静态VLAN--常用 5.1.1静态vlan的范围 5.2动态VLAN 6、VLAN的三种端口类型 6.1Access接口 6.2Trunk接口 6.3Hybrid接口 二、配置…

Nodejs 第二十三章(Markdown 转 html)

Markdown 转换html 是一个非常常见的需求 什么是 Markdown ? Markdown 是一种轻量级标记语言&#xff0c;它允许人们使用易读易写的纯文本格式编写文档。 我们需要用到三个库实现 EJS&#xff1a;一款强大的JavaScript模板引擎&#xff0c;它可以帮助我们在HTML中嵌入动态内…

linux中堡垒机

堡垒机 堡垒机概念目的 安装Jumpserver使用资产管理资产列表创建需要管理的服务器创建用户权限管理页面进行资产授权操作视频 应用管理应用管理页面创建需要管理的应用&#xff0c;这里用数据库mysql举例进入后点击创建资产管理创建登录应用所需的用户选择创建mysql关系型数据库…

IP地址在流量管理中的作用

随着互联网的快速发展&#xff0c;流量管理已成为各行业面临的重要问题。IP地址作为一种标识网络中设备的重要标识符&#xff0c;在流量管理中发挥着重要作用。本文将介绍IP地址在流量管理中的应用&#xff0c;以帮助读者更好地理解这一领域的发展。 一、IP地址的分类与标识 I…

【C++】输入输出流 ⑥ ( cout 标准输出流对象 | cout 常用 api 简介 | cout.put(char c) 函数 )

文章目录 一、cout 标准输出流对象1、cout 标准输出流对象简介2、cout 常用 api 简介 二、cout.put(char c) 函数1、cout.put(char c) 函数 简介2、代码示例 - cout.put(char c) 函数 一、cout 标准输出流对象 1、cout 标准输出流对象简介 cout 是 标准输出流 对象 , 是 ostrea…

聚焦本田XR-V和福特领睿:两大SUV综合实力对比,谁更胜一筹?

在当今的SUV市场中&#xff0c;家庭用户的选择变得越来越多样化。特别是对于那些追求时尚、功能性以及技术先进性的用户来说&#xff0c;选择正确的SUV显得尤为重要。本文将重点对比福特领睿和本田XR-V这两款SUV&#xff0c;探讨它们在各方面的表现&#xff0c;做一个综合实力的…

GPTs prompts灵感库:创意无限,专业级创作指南,打造吸睛之作的秘诀

GPTs prompts灵感库&#xff1a;创意无限&#xff0c;专业级创作指南&#xff0c;打造吸睛之作的秘诀 优质prompt展示 1.1 极简翻译 中英文转换 你是一个极简翻译工具&#xff0c;请在对话中遵循以下规则&#xff1a; - Prohibit repeating or paraphrasing any user instru…

Vue运用之input本地上传文件,实现传参file:(binary)

前言 功能场景是,实现列表的【批量导入】的效果,在Excel里维护好信息,本地上传好文件,再点击【确认】触动接口,将flie信息传值后端接口。 html代码 input的type设置为file,支持格式设置为仅支持Excel类型 <div class="btn-box"><div class=&quo…

HNU数据库大作业-世界杯比赛系统

前言 之前做的那个版本bug较多&#xff0c;后进行了大量优化。 此项目是一个前后端分离的项目&#xff0c;前端主要使用htmlcssjs搭建&#xff0c;使用的是layui框架 后端使用php语言&#xff0c;仅实现了简单的查询数据库功能&#xff0c;无法实现多并发查询等复杂情况 数…

LeetCode刷题--- 验证二叉搜索树

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 http://t.csdnimg.cn/ZxuNL个人专栏&#xff1a;力扣递归算法题 http://t.csdnimg.cn/ZxuNL 【C】 http://t.csdnimg.cn/c9twt 前言&#xff1a;这个专栏主要讲述递归递归、搜索与回溯算法&#x…

想学精MySQL,得先捋一捋高可用架构

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

Web漏洞分析-文件解析及上传(中)

随着互联网的迅速发展&#xff0c;网络安全问题变得日益复杂&#xff0c;而文件解析及上传漏洞成为攻击者们频繁攻击的热点之一。本文将深入研究文件解析及上传漏洞&#xff0c;通过对文件上传、Web容器IIS、命令执行、Nginx文件解析漏洞以及公猫任意文件上传等方面的细致分析&…

JavaScript API: IntersectionObserver

简介 IntersectionObserver 是一个 JavaScript API&#xff0c;用于监测一个元素与其父元素或视窗的交叉状态。它可以用来判断一个元素是否可见或者在视窗中的位置是否发生变化。 使用 IntersectionObserver&#xff0c;你可以注册一个回调函数&#xff0c;当被观察的元素进入…

ChatGPT生成的docx文档压缩Python代码

对DOCX文件中的图片进行缩小处理 这份Python脚本旨在处理给定的DOCX&#xff08;Word文档&#xff09;文件中的图片&#xff0c;将其按照指定的比例进行缩小&#xff0c;并生成一个新的压缩版DOCX文件&#xff0c;其中包含经过缩小处理的图片。 代码功能概览&#xff1a; 导入…

.NET如何调用Web Service服务?

我们知道&#xff0c;现在用Web Service提供对外接口的项目其实很少了&#xff0c;现在大部分应用都是b/s端的了&#xff0c;WebApi的优势自然而然就体现出来了&#xff0c;可自定义请求头部信息、可对数据进行缓存、使用json字符串让开发更加灵活。那么Web Service是不是就无用…

高校刮起元宇宙风!3DCAT实时云渲染助力川轻化元校园建设

元宇宙&#xff0c;是一个虚拟的网络世界&#xff0c;它与现实世界相互连接&#xff0c;为人们提供了一个身临其境的数字体验。元宇宙的概念并不新鲜&#xff0c;早在上个世纪就有科幻作家和电影导演对它进行了想象和创造。但是&#xff0c;随着科技的发展&#xff0c;特别是5G…

2023最新大模型实验室解决方案

人工智能是引领未来的新兴战略性技术&#xff0c;是驱动新一轮科技革命和产业变革的重要力量。近年来&#xff0c;人工智能相关技术持续演进&#xff0c;产业化和商业化进程不断提速&#xff0c;正在加快与千行百业深度融合。 大模型实验室架构图 大模型实验室建设内容 一、课…