当前位置: 首页 > article >正文

【HeadFirst系列之HeadFirst设计模式】第18天之蝇量模式(Flyweight Pattern):优化资源的秘密武器

蝇量模式(Flyweight Pattern):优化资源的秘密武器

在软件开发中,当系统需要创建大量相似对象时,内存占用和性能问题就会浮出水面。《Head First 设计模式》介绍了 蝇量模式(Flyweight Pattern),这是一种优化对象复用的结构型设计模式,旨在减少对象创建的内存开销。本文将深入剖析蝇量模式的核心内容,并结合 JDK 和 Spring 框架中的应用 进行实践探讨。


1. 遇到什么问题?

场景:大量重复对象导致内存占用过高

假设我们要开发一款绘图应用,支持绘制大量的“树木”对象,每棵树都有以下属性:

  • 内部状态(Intrinsic State): 颜色、树种、形状等,所有相同种类的树共享相同的属性。
  • 外部状态(Extrinsic State): 坐标(X、Y)、环境信息等,每棵树的位置信息不同。

如果每棵树都是一个独立的对象,并存储所有属性,那么 上千棵树可能会占用大量内存,导致应用性能下降。


2. 怎么解决?

引入蝇量模式

蝇量模式的核心思想是 将共享部分(内部状态)抽取出来,避免不必要的重复存储,而唯一的不同信息(外部状态)由客户端传递。
这样,相同种类的树可以复用同一个对象,而位置信息等变化属性则由外部提供。

核心设计

  • Flyweight(蝇量对象): 共享的对象,包含内部状态。
  • FlyweightFactory(工厂类): 负责管理和复用 Flyweight 对象,确保相同的对象不会重复创建。
  • Client(客户端): 负责存储外部状态,并在需要时从工厂获取共享对象。

3. 代码实现

我们以“绘制森林中的树木”为例,使用 Java 代码 实现蝇量模式:

(1)创建 Flyweight 接口

// 蝇量接口,定义共享方法
public interface TreeFlyweight {void display(int x, int y); // 外部状态由方法参数传入
}

(2)具体的 Flyweight 类

// 具体的树对象,包含共享的内部状态
public class Tree implements TreeFlyweight {private final String type;  // 树的种类private final String color; // 颜色private final String texture; // 纹理public Tree(String type, String color, String texture) {this.type = type;this.color = color;this.texture = texture;}@Overridepublic void display(int x, int y) {System.out.println("绘制 " + type + " 树,颜色: " + color + ",纹理: " + texture + ",位置: (" + x + "," + y + ")");}
}

(3)创建 FlyweightFactory 负责管理共享对象

import java.util.HashMap;
import java.util.Map;// 工厂类,管理共享对象
public class TreeFactory {private static final Map<String, TreeFlyweight> treeCache = new HashMap<>();public static TreeFlyweight getTree(String type, String color, String texture) {String key = type + "-" + color + "-" + texture;if (!treeCache.containsKey(key)) {treeCache.put(key, new Tree(type, color, texture));System.out.println("创建新树对象:" + key);} else {System.out.println("复用已有树对象:" + key);}return treeCache.get(key);}
}

(4)客户端使用 Flyweight

public class FlyweightPatternDemo {public static void main(String[] args) {// 创建多个树对象,但只会创建必要的不同种类树,其他复用TreeFlyweight tree1 = TreeFactory.getTree("Oak", "Green", "Smooth");tree1.display(10, 20);TreeFlyweight tree2 = TreeFactory.getTree("Oak", "Green", "Smooth");tree2.display(30, 40);TreeFlyweight tree3 = TreeFactory.getTree("Pine", "Dark Green", "Rough");tree3.display(50, 60);}
}

(5)运行结果

创建新树对象:Oak-Green-Smooth
绘制 Oak 树,颜色: Green,纹理: Smooth,位置: (10,20)
复用已有树对象:Oak-Green-Smooth
绘制 Oak 树,颜色: Green,纹理: Smooth,位置: (30,40)
创建新树对象:Pine-Dark Green-Rough
绘制 Pine 树,颜色: Dark Green,纹理: Rough,位置: (50,60)

说明:

  • Oak-Green-Smooth 只创建了一次,后续直接复用。
  • Pine-Dark Green-Rough 由于是新的类型,所以创建新的对象。

4. 蝇量模式的应用场景

(1)JDK 中的应用

  • Java String 常量池:

    String s1 = "hello";
    String s2 = "hello";
    System.out.println(s1 == s2); // true(字符串池复用)
    

    JDK 采用 字符串池(String Pool) 机制复用字符串对象,避免重复创建。

  • Integer.valueOf() 复用小整数对象(-128 ~ 127):

    Integer a = Integer.valueOf(127);
    Integer b = Integer.valueOf(127);
    System.out.println(a == b); // true(缓存复用)
    

    JDK 通过 IntegerCache 复用小整数,减少对象创建。

(2)Spring 框架中的应用

  • Spring Bean 作用域(Scope)中的单例模式

    • 默认情况下,Spring 管理的 Bean 是 单例模式,所有请求共享同一个 Bean 实例,相当于全局的蝇量对象。
    • 例如:
      @Component
      @Scope("singleton") // 只创建一个实例
      public class SingletonService { }
      
  • Spring MVC 中的视图对象复用

    • 视图解析器会复用 View 对象,避免重复创建。

5. 蝇量模式的优缺点

优点

减少内存占用:通过对象共享,降低内存消耗。
提高性能:避免重复创建对象,优化资源利用。
适用于大量重复对象的场景:如缓存、池化对象等。

缺点

引入了额外的管理逻辑:需要管理对象池和工厂。
可能导致线程安全问题:共享对象需要考虑并发访问。
不适用于对象状态差异很大的场景:如果对象的外部状态过多,模式的优势就会减少。


6. 总结

  • 蝇量模式通过共享对象,减少系统资源开销,优化性能。
  • 适用于大量相似对象的场景,如缓存、池化技术。
  • JDK 和 Spring 中广泛使用,如 String 常量池、IntegerCache、Spring 单例 Bean。
  • 在使用时,需要权衡管理复杂度和性能优化的收益。

如果你的系统面临大量重复对象的内存压力,不妨考虑蝇量模式来优化! 🚀

相关文章:

【HeadFirst系列之HeadFirst设计模式】第18天之蝇量模式(Flyweight Pattern):优化资源的秘密武器

蝇量模式&#xff08;Flyweight Pattern&#xff09;&#xff1a;优化资源的秘密武器 在软件开发中&#xff0c;当系统需要创建大量相似对象时&#xff0c;内存占用和性能问题就会浮出水面。《Head First 设计模式》介绍了 蝇量模式&#xff08;Flyweight Pattern&#xff09;…...

微信小程序将markdown内容转为pdf并下载

要在微信小程序中将Markdown内容转换为PDF并下载,您可以使用以下方法: 方法一:使用第三方API服务 选择第三方API服务: 可以选择像 Pandoc、Markdown-PDF 或 PDFShift 这样的服务,将Markdown转换为PDF。例如,PDFShift 提供了一个API接口,可以将Markdown内容转换为PDF格式…...

SQL CHAR_LENGTH返回字符串长度的函数

CHAR_LENGTH 是 SQL 中的一个用于返回字符串长度的函数。它计算的是字符串中的字符数&#xff0c;而不是字节数。这在处理多字节字符集&#xff08;如 UTF-8&#xff09;时尤其有用&#xff0c;因为一个字符可能会占用多个字节。 CHAR_LENGTH(string) string 是要计算长度的字…...

sqlserver删除表记录语句,及删除表时清零ID的SQL语句

sqlserver中&#xff0c;删除表中所有记录的语句如下 Delete from tableName 例&#xff0c;删除表logs的所有记录 sqlserver&#xff0c;删除表中所有数据&#xff0c;标识列ID归零&#xff0c;保留表结构的语句 truncate table tableName 例&#xff0c;删除表logs的所…...

求最大公约数问题(信息学奥赛一本通-1207)

【题目描述】 给定两个正整数&#xff0c;求它们的最大公约数。 【输入】 输入一行&#xff0c;包含两个正整数(<1,000,000,000)。 【输出】 输出一个正整数&#xff0c;即这两个正整数的最大公约数。 【输入样例】 6 9 【输出样例】 3 【题解代码】 #include<bits/stdc…...

Vue3中动态Ref的魔法:绑定与妙用

前言 在Vue 3的开发过程中,动态绑定Ref是一项非常实用的技术,特别是在处理复杂组件结构和动态数据时。通过动态绑定Ref,我们可以更灵活地访问和操作DOM元素或组件实例,实现更高效的交互和状态管理。本文将详细介绍如何在Vue 3中实现动态Ref的绑定,并通过实例展示其妙用。…...

Conda常用命令汇总

Conda 是一个流行的包管理器和环境管理工具&#xff0c;广泛应用于数据科学、机器学习等领域。它可以帮助我们管理 Python 包以及不同版本的环境&#xff0c;避免包冲突&#xff0c;提升项目的可复现性。以下是一些常用的 Conda 命令&#xff0c;涵盖环境创建、管理、包安装等常…...

2025年科技趋势深度解析:从“人工智能+”到量子跃迁的技术革命

一、“人工智能”国家战略&#xff1a;重塑产业生态的核心引擎 2025年政府工作报告首次将"人工智能"提升至国家战略层面&#xff0c;标志着AI技术正式成为驱动产业升级的核心力量。据麦肯锡最新研究显示&#xff0c;中国云计算市场规模已突破8315亿元&#xff0c;其…...

【瞎折腾/ragflow】构建docker镜像并部署使用ragflow

说在前面 操作系统&#xff1a;win11docker desktop版本&#xff1a;4.29.0docker engin版本&#xff1a;v26.0.0ragflow版本&#xff1a;nightly 安装docker 官网 如果是win11&#xff0c;backend建议使用wsl2 安装好后打开docker desktop&#xff0c;不然docker命令用不了 …...

哈弗赛恩公式计算长度JavaScript实现

哈弗赛恩公式&#xff08;Haversine formula&#xff09;是一种用于计算球面上两点间最短距离的数学方法&#xff0c;尤其适用于地球表面。本文将详细介绍哈弗赛恩公式的原理、应用以及如何使用JavaScript实现它。 一、哈弗赛恩公式原理 在球面几何中&#xff0c;哈弗赛恩公式…...

Pytest框架中的Fixture:深入理解与实际应用

Pytest是Python中最流行的测试框架之一&#xff0c;以其简洁的语法和强大的功能而闻名。在Pytest中&#xff0c;fixture是一个非常重要的概念&#xff0c;它允许我们在测试函数执行前后进行一些准备工作或清理工作。本文将深入探讨fixture的使用方法、实际应用场景以及一些高级…...

大模型赋能金融行业:从理念到落地实践

思维导图 引言 &#x1f31f; 随着人工智能技术的飞速发展&#xff0c;大模型正在重塑各行各业&#xff0c;金融领域尤为明显。本文将基于业内领先金融科技公司的实践经验&#xff0c;系统探讨大模型在金融行业的落地应用、面临的挑战以及未来的发展方向。从AI发展历程、能力边…...

数据结构篇——串(String)

一、引入 在计算机中的处理的数据内容大致可分为以整形、浮点型等的数值处理和字符、字符串等的非数值处理。 今天我们主要学习的就是字符串数据。本章主要围绕“串的定义、串的类型、串的结构及其运算”来进行串介绍与学习。 二、串的定义 2.1、串的基本定义 串&#xff08;s…...

数据结构--【顺序表与链表】笔记

顺序表 template <class T> class arrList :public List<T> //表示 arrList 类以公有继承的方式继承自 List<T> 类 //公有继承意味着 List<T> 类的公共成员在 arrList 类中仍然是公共成员&#xff0c;受保护成员在 arrList 类中仍然是受保护成员。 { …...

算法.习题篇

算法 — 地大复试 模拟 while循环和MOD循环计数 1.约瑟夫问题 http://bailian.openjudge.cn/practice/3254 using namespace std;bool isNoPeople(vector<bool> c)//判断当前数组是否一个小孩都没有了 {bool nopeople true;for (bool ival : c){if ( ival true)nop…...

大语言模型进化论:从达尔文到AI的启示与展望

文章大纲 引言大语言模型中的“进化论”思想体现遗传变异过度繁殖和生存斗争大模型“过度繁殖”与“生存竞争”机制解析**一、过度繁殖:技术迭代的指数级爆发****二、生存竞争:计算资源的达尔文战场****三、生存竞争胜出关键要素****四、行业竞争格局演化趋势**核心结论自然选…...

MES机联网4:文档资料

目录信息 MES机联网1&#xff1a;技术方案MES机联网2&#xff1a;采集网关MES机联网3&#xff1a;管理后台MES机联网4&#xff1a;文档资料 MQ接入文档 1、建立连接 mqtt连接地址: 192.168.0.138 mqtt端口: 1883 mqtt用户名&#xff1a;admin mqtt密码&#xff1a;123456 …...

编程考古-Borland历史:《.EXE Interview》对Anders Hejlsberg关于Delphi的采访内容(上)

为了纪念Delphi在2002年2月14日发布的25周年(2020.2.12),这里有一段由.EXE杂志编辑Will Watts于1995年对Delphi首席架构师Anders Hejlsberg进行的采访记录。在这次采访中,Anders讨论了Delphi的设计与发展,以及即将到来的针对Windows 95的32位版本。 问: Delphi是如何从T…...

系统架构设计师—系统架构设计篇—基于体系结构的软件开发方法

文章目录 概述基于体系结构的开发模型-ABSDM体系结构需求体系结构设计体系结构文档化体系结构复审体系结构实现体系结构演化 概述 基于体系结构&#xff08;架构&#xff09;的软件设计&#xff08;Architecture-Based Software Design&#xff0c;ABSD&#xff09;方法。 AB…...

国产AI智能体manus和deepseek的区别

DeepSeek&#xff08;深度求索&#xff09;与Manus&#xff08;全球首款通用AI助手&#xff09;是当前中国AI领域的两大代表性产品&#xff0c;但两者的定位、技术路径与应用场景存在显著差异。以下从多个维度进行详细对比&#xff1a; 1. 核心定位与技术架构 DeepSeek 定位&am…...

Maven快速入门指南

Maven快速入门指南&#xff1a;从依赖管理到项目构建全解析 文章目录 Maven快速入门指南&#xff1a;从依赖管理到项目构建全解析一、认识Maven&#xff1a;Java项目的瑞士军刀1.1 什么是Maven&#xff1f;1.2 Maven的三大核心作用 二、快速安装配置2.1 环境准备2.2 安装步骤&a…...

linux 内网下载 yum 依赖问题

1.上传系统镜像 创建系统目录&#xff0c;用户存放镜像&#xff0c;如下&#xff1a; mkdir /mnt/iso上传 iso 文件到 /mnt/iso 文件夹下。 2.挂载系统镜像 安装镜像至 /mnt/cdrom 目录中 mount -o loop /mnt/iso/CentOS-7-x86_64-Minimal-xx.iso /mnt/cdrom3.修改yum源配…...

基于Python+Django的网上招聘管理系统

项目介绍 PythonDjango网上招聘系统的设计与实现(Pycharm Django Vue Mysql) 平台采用B/S结构&#xff0c;后端采用主流的Python语言进行开发&#xff0c;前端采用主流的Vue.js进行开发。整个平台包括前台和后台两个部分。 - 前台功能包括&#xff1a;首页、岗位详情页、简历中…...

人生意气场概念解析

人生意气场 浅析人生意气场缘起为己之学悠然采菊面相方程组花间流风积分形式与梅易字品微分形式导引修正&#xff1a; 切触形式和结构的数学定义及名词解释切触形式α切触结构ξ 数学定义与解析"反者道之动&#xff0c;弱者道之用"慢道缓行理性人大语言模型量化解析太…...

数据仓库为什么要分层

数据仓库分层架构是数据仓库设计中的一个重要概念&#xff0c;其主要目的是为了更好地组织和管理数据&#xff0c;提高数据仓库的可维护性、可扩展性和性能。分层架构将数据仓库划分为多个层次&#xff0c;每个层次都有其特定的职责和功能。以下是数据仓库分层的主要原因和好处…...

番外篇 - Docker的使用

一、Docker的介绍 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从Apache2.0协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。 容器是完…...

mapbox开发小技巧

自定义图标 // 1、单个图标 const url ./static/assets/symbols/code24x24/VIDEO.png // 图标路径 map.loadImage(url ,(error, image) > {if (error) throw errormap.addImage(video-icon, image) })// 2、雪碧图利用canvas // json和png图片 function getStyleImage(fil…...

Vue23Web 基礎性拉滿的面試題(2025版)還沒更新完...

Vue2&3 基礎性1. 關於Vue2和Vue3生命週期的差別2. Vue2&3組件之間傳參不同點Vue2 傳遞與接收Vue3 傳遞與接收 (使用script setup語法糖)Vue3 傳遞與接收 (不使用script setup語法糖) 3. Vue2&3 keep-alive 組件Vue2 keep-aliveVue3 keep-alive 進階性爲什麽POST請求…...

GitHub神秘组织3小时极速复刻Manus

一、背景 昨夜科技圈被两个关键词刷屏&#xff1a;​Manus激活码炒至6万&#xff0c;​GitHub神秘项目OpenManus突然开源。 Manus之所以如此火爆&#xff0c;是因为在演示视频中自主分析股票、筛选简历、规划旅行的能力。同时&#xff0c;想要体验Manus就需要内测邀请码&…...

文件上传漏洞(upload靶场)

目录 Pass-01&#xff1a;前端绕过 方法一&#xff1a;浏览器禁用js 方法二:直接修改或删除js脚本 方法三&#xff1a;修改后缀绕过 Pass-02:服务器检测 Pess-03:黑名单绕过 Pass-04:.htaccess文件 Pass-05:windows特性和user.ini 方法一&#xff1a;php.自动解析为ph…...