java23种设计模式-享元模式

news/2025/2/27 1:08:59

享元模式(Flyweight Pattern)学习笔记

1. 模式定义

结构型设计模式,通过共享技术实现大量细粒度对象的复用,有效减少内存占用并提高性能。核心思想:分离内部状态(可共享)与外部状态(不可共享)

2. 适用场景

✅ 系统中存在大量相似对象

✅ 对象的大部分状态可以外部化

✅ 需要缓存池或对象池的应用

✅ 需要减少内存占用和提高性能的场景

3. 模式结构

creates
requests
FlyweightFactory
-pool: Map
+getFlyweight(key)
«interface»
Flyweight
+operation(extrinsicState)
ConcreteFlyweight
-intrinsicState
+operation(extrinsicState)
UnsharedConcreteFlyweight
-allState
+operation(extrinsicState)
Client
-flyweights: List
+addFlyweight()
+executeOperations()

4. 核心角色

角色说明
Flyweight抽象享元接口,定义操作接口
ConcreteFlyweight具体享元类,包含内部状态(可共享)
UnsharedConcreteFlyweight非共享具体享元类(可选)
FlyweightFactory享元工厂类,管理享元对象池
Client客户端,维护外部状态并调用享元对象

5. 状态说明

状态类型说明
内部状态存储在享元对象内部,可以被多个上下文共享的信息
外部状态随上下文变化的信息,由客户端保存并在调用时传入

6. 代码示例

6.1 文字编辑器字符对象

java">// 抽象享元
interface Character {
    void display(int x, int y, String color);
}

// 具体享元
class ConcreteCharacter implements Character {
    private char symbol;  // 内部状态
    
    public ConcreteCharacter(char symbol) {
        this.symbol = symbol;
    }

    @Override
    public void display(int x, int y, String color) {  // 外部状态
        System.out.printf("显示字符 %c 在(%d,%d),颜色:%s%n", symbol, x, y, color);
    }
}

// 享元工厂
class CharacterFactory {
    private Map<Character, Character> pool = new HashMap<>();
    
    public Character getCharacter(char key) {
        if (!pool.containsKey(key)) {
            pool.put(key, new ConcreteCharacter(key));
        }
        return pool.get(key);
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        CharacterFactory factory = new CharacterFactory();
        
        List<Character> document = new ArrayList<>();
        document.add(factory.getCharacter('H'));
        document.add(factory.getCharacter('e'));
        document.add(factory.getCharacter('l'));
        document.add(factory.getCharacter('l'));
        document.add(factory.getCharacter('o'));

        int x = 0;
        for (Character c : document) {
            c.display(x++, 0, "black");  // 传递外部状态
        }
    }
}

7. 模式变种

  1. 复合享元模式:将多个单纯享元组合成复合对象
  2. 线程级享元:结合ThreadLocal实现线程级共享
  3. 带缓存清理机制:实现LRU缓存策略管理享元对象

8. 优缺点分析

✔️ 优点

  • 极大减少内存中对象的数量
  • 外部状态相对独立,增强程序灵活性
  • 享元对象可被不同场景复用

缺点

  • 增加系统复杂度(需要分离内外状态)
  • 需要额外关注线程安全问题
  • 可能影响程序执行效率(查找/计算外部状态)

9. 相关模式对比

模式目的关键区别
单例模式控制实例数量享元可能有多个不同实例
原型模式对象克隆享元强调共享已有对象
对象池模式重用对象对象池管理临时对象,享元管理永久对象

10. 实际应用案例

  • Java String常量池(-128~127的Integer缓存)
  • 棋牌游戏的棋子对象管理
  • 文档编辑器中的字符/段落格式
  • 图形编辑器中的图形对象
  • 数据库连接池

11. 最佳实践建议

  1. 严格区分内部状态和外部状态
  2. 使用不可变对象作为享元对象
  3. 对享元工厂实现缓存淘汰策略(LRU)
  4. 考虑使用WeakReference管理享元池
  5. 外部状态参数尽量使用基本类型或不可变对象
  6. 多线程环境下需要同步处理享元工厂

🧩 记忆技巧:把享元模式想象成"共享单车"系统,单车(内部状态)是共享的,用户(外部状态)各自的使用位置不同。


http://www.niftyadmin.cn/n/5869338.html

相关文章

显式指定 ChromeDriver 路径

‌1️⃣ 显式指定 ChromeDriver 路径‌ 在代码中直接传递驱动路径&#xff0c;绕过 Selenium Manager 的自动检测&#xff1a; pythonCopy Code from selenium import webdriver from selenium.webdriver.chrome.service import Service# 指定 ChromeDriver 绝对路径&#xf…

Win32/ C++ 简易对话框封装框架(多语言, 通知栏菜单, 拖拽文件处理)

Win32 简易对话框封装简易框架示例 1. 菜单操作: 多语言 2. 通知栏图标菜单 3. 其他操作: 接受拖拽文件等等 CDialogFrame.h #pragma once #include "CWindow/CDialogBase.h" #include "CNSFHeader.h" #include "Win32Utils/CBytesUtils.h" …

第二十:【路由的props配置】

作用&#xff1a;让路由组件更方便的收到参数&#xff08;可以将路由参数作为props传给组件&#xff09; {name:xiang,path:detail/:id/:title/:content,component:Detail, ​ 第一种方法&#xff1a;// props的对象写法&#xff0c;作用&#xff1a;把对象中的每一组key-valu…

探索浮点数在内存中的存储(附带快速计算补码转十进制)

目录 一、浮点数在内存中的存储 1、常见的浮点数&#xff1a; 2、浮点数存储规则&#xff1a; 3、内存中无法精确存储&#xff1a; 4、移码与指数位E&#xff1a; 5、指数E的三种情况&#xff1a; 二、快速计算补码转十进制 1、第一种方法讨论&#xff1a; 2、第二种方…

货车一键启动无钥匙进入手机远程启动的正确使用方法

一、移动管家货车无钥匙进入系统的使用方法 基本原理&#xff1a;无钥匙进入系统通常采用RFID无线射频技术和车辆身份识别码识别系统。车钥匙需要随身携带&#xff0c;当车钥匙靠近货车时&#xff0c;它会自动与货车的解码器匹配。开门操作&#xff1a;当靠近货车后&#xff0…

AI Agent Service Toolkit:一站式大模型智能体开发套件

项目简介 该工具包基于LangGraph、FastAPI和Streamlit构建,提供了构建和运行大模型Agent的最小原子能力,包含LangGraph代理、FastAPI服务、用于与服务交互的客户端以及一个使用客户端提供聊天界面的Streamlit应用。用户可以利用该工具包提供的模板快速搭建基于LangGraph框架…

WebSocket简单介绍 并接入deepseek

目录 什么是 WebSocket&#xff1f;工作原理&#xff1a; 为什么需要 WebSocket&#xff1f;WebSocket 的优势HTTP 和 WebSocket 的区别WebSocket 的劣势WebSocket 的应用场景WebSocket 握手过程1. 客户端发起握手请求2. 服务器响应握手请求3. 建立连接 WebSocket 事件处理WebS…

机器视觉--相机曝光

在现代工业生产的精密舞台上&#xff0c;机器视觉技术已然成为推动生产自动化、智能化的关键力量。而工业相机作为机器视觉系统的 “眼睛”&#xff0c;其曝光环节更是决定了视觉信息获取的质量与精度&#xff0c;如同为工业生产赋予了一双洞察入微的 “智慧之眼”&#xff0c;…