(十 二)趣学设计模式 之 享元模式!

news2025/4/5 23:36:30

在这里插入图片描述

目录

    • 一、 啥是享元模式?
    • 二、 为什么要用享元模式?
    • 三、 享元模式的实现方式
    • 四、 享元模式的优缺点
    • 五、 享元模式的应用场景
    • 六、 总结

🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!
🌟了解组合模式请看: (十 一)趣学设计模式 之 组合模式!
✨更多请看个人主页: 码熔burning

这篇文章带你详细认识一下设计模式中的享元模式

一、 啥是享元模式?

想象一下,你正在玩一个大型的在线游戏 🎮。 游戏中有成千上万的士兵 💂,每个士兵都有自己的位置、生命值、装备等等。 如果为每个士兵都创建一个完整的对象,会消耗大量的内存 🧠。 但是,很多士兵的外观、属性都是相同的,只有位置不同。

享元模式,就是运用共享技术有效地支持大量细粒度的对象! 享元模式通过共享尽可能多的对象来最小化内存使用 💾。

简单来说,就是把对象的状态分成内部状态和外部状态,共享内部状态,减少对象数量! ♻️

  • 你的程序需要创建大量的相似对象: 就像游戏中的士兵 🎮💂!
  • 对象的很多状态都可以共享: 就像士兵的外观、属性 🎮!
  • 你想减少内存消耗: 就像你想让游戏运行更流畅 🧠!

二、 为什么要用享元模式?

用享元模式,好处多多 👍:

  • 减少内存消耗: 通过共享对象,减少内存占用 💾!
  • 提高性能: 减少对象创建和销毁的开销 🚀!
  • 提高系统扩展性: 可以支持更多的对象 ➕!

三、 享元模式的实现方式

享元模式主要包含以下几个角色:

  • Flyweight(享元): 定义享元对象的接口,声明可以被共享的内部状态,并提供接受外部状态的方法。 🎮💂 (比如:士兵的基类)
  • ConcreteFlyweight(具体享元): 实现享元接口,存储内部状态。 🎮💂 (比如:具体的士兵对象)
  • UnsharedConcreteFlyweight(非共享具体享元): 不是共享的享元对象,通常包含一些不能被共享的状态。 (比如:拥有特殊装备的士兵)
  • FlyweightFactory(享元工厂): 创建和管理享元对象,确保享元对象可以被共享。 🏭 (比如:士兵工厂)
  • Client(客户端): 使用享元对象,并提供外部状态。 🎮 (比如:游戏客户端)

内部状态: 指的是对象可以共享的状态,存储在享元对象内部,不会随着环境改变而改变。 (比如:士兵的外观、属性)
外部状态: 指的是对象不能共享的状态,需要由客户端提供,会随着环境改变而改变。 (比如:士兵的位置、生命值)

代码示例:

import java.util.HashMap;
import java.util.Map;

// 享元:士兵接口
public interface Soldier {
    void display(int x, int y); // 显示士兵
}

// 具体享元:士兵
public class ConcreteSoldier implements Soldier {
    private String model; // 士兵模型

    public ConcreteSoldier(String model) {
        this.model = model;
    }

    @Override
    public void display(int x, int y) {
        System.out.println("士兵模型:" + model + ",位置:(" + x + ", " + y + ")");
    }
}

// 享元工厂:士兵工厂
public class SoldierFactory {
    private static Map<String, Soldier> soldierMap = new HashMap<>(); // 存储士兵对象

    public static Soldier getSoldier(String model) {
        Soldier soldier = soldierMap.get(model);
        if (soldier == null) {
            soldier = new ConcreteSoldier(model);
            soldierMap.put(model, soldier);
        }
        return soldier;
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        Soldier soldier1 = SoldierFactory.getSoldier("步兵"); // 获取步兵
        soldier1.display(10, 20); // 显示步兵

        Soldier soldier2 = SoldierFactory.getSoldier("步兵"); // 获取步兵
        soldier2.display(30, 40); // 显示步兵

        Soldier soldier3 = SoldierFactory.getSoldier("骑兵"); // 获取骑兵
        soldier3.display(50, 60); // 显示骑兵

        System.out.println("士兵数量:" + SoldierFactory.soldierMap.size()); // 输出士兵数量
    }
}

分析:

  • Soldier 是享元接口,定义了士兵的显示方法。
  • ConcreteSoldier 是具体享元,实现了士兵接口,存储了士兵的模型。
  • SoldierFactory 是享元工厂,创建和管理士兵对象,确保相同模型的士兵对象只创建一个。

输出结果:

士兵模型:步兵,位置:(10, 20)
士兵模型:步兵,位置:(30, 40)
士兵模型:骑兵,位置:(50, 60)
士兵数量:2

可以看到,虽然创建了三个士兵对象,但是实际只创建了两个士兵对象,因为步兵对象被共享了。

四、 享元模式的优缺点

优点:

  • 减少内存消耗 💾!
  • 提高性能 🚀!
  • 提高系统扩展性 ➕!

缺点:

  • 增加了系统的复杂度 😫!
  • 需要分离内部状态和外部状态,设计难度较高 🧠!
  • 共享对象的状态不可修改,否则会影响其他使用该对象的客户端 🔒!

五、 享元模式的应用场景

  • 当你的程序需要创建大量的相似对象时: 就像游戏中的士兵 🎮💂!
  • 对象的很多状态都可以共享: 就像士兵的外观、属性 🎮!
  • 你想减少内存消耗: 就像你想让游戏运行更流畅 🧠!
  • 文本编辑器: 文本编辑器可以使用享元模式来共享字符对象,减少内存消耗。
  • 数据库连接池: 数据库连接池可以使用享元模式来共享数据库连接对象,提高性能。

六、 总结

  • 享元模式就像把对象的状态分成内部状态和外部状态,共享内部状态,减少对象数量! ♻️
  • 主要包含享元、具体享元、非共享具体享元和享元工厂四个角色! 🎭
  • 优点是减少内存消耗、提高性能、提高系统扩展性! 👍
  • 缺点是增加复杂度、设计难度较高、共享对象的状态不可修改! 👎
  • 适用于需要创建大量的相似对象,且对象的很多状态都可以共享的场景! 🎯

希望这篇文章能让你彻底理解享元模式! 💯 祝你学习愉快! 😄
看完请看:(十 三)趣学设计模式 之 模版方法模式!

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

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

相关文章

Trae:国内首款AI原生IDE,编程效率大提升

今年一月&#xff0c;在新闻上看到字节跳动面向海外市场推出了一款名为Trae的AI集成开发环境&#xff08;IDE&#xff09;。起初&#xff0c;我并未给予过多关注&#xff0c;因为市面上已有不少IDE集成了AI插件&#xff0c;功能也非常全面&#xff0c;而字节跳动自家的MarsCode…

RocketMQ定时/延时消息实现机制

RocketMQ 的延迟消息是其核心特性之一&#xff0c;允许消息在指定延迟时间后才被消费者消费。 定时消息生命周期 一、延迟消息的核心机制 RocketMQ&#xff08;5.0之前&#xff09; 不支持任意时间精度的延迟&#xff0c;而是通过预定义的 延迟级别&#xff08;Delay Level&a…

基于SpringBoot的校园二手交易平台(源码+论文+部署教程)

运行环境 校园二手交易平台运行环境如下&#xff1a; • 前端&#xff1a;Vue • 后端&#xff1a;Java • IDE工具&#xff1a;IntelliJ IDEA&#xff08;可自行更换&#xff09; • 技术栈&#xff1a;SpringBoot Vue MySQL 主要功能 校园二手交易平台主要包含前台和…

利用 LangChain 和一个大语言模型(LLM)构建一个链条,自动从用户输入的问题中提取相关的 SQL 表信息,再生成对应的 SQL 查询

示例代码&#xff1a; from langchain_core.runnables import RunnablePassthrough from langchain.chains import create_sql_query_chain from operator import itemgetter from langchain.chains.openai_tools import create_extraction_chain_pydantic# 系统消息&#xff…

力扣hot 100之矩阵四题解法总结

本期总结hot100 中二维矩阵的题&#xff0c;时空复杂度就不分析了 1.矩阵置零 原地标记&#xff0c;用第一行和第一列作为当前行列是否为0的标记&#xff0c;同时用两个标签分别记录0行、0列的标记空间中原本是否有0 class Solution:def setZeroes(self, matrix: List[List[…

在Linux上使用APT安装Sniffnet的详细步骤

一、引言 Sniffnet 是一款开源的网络流量监控工具&#xff0c;适用于多种Linux发行版。如果你的Linux系统使用APT&#xff08;Advanced Package Tool&#xff09;作为包管理器&#xff0c;以下是如何通过APT安装Sniffnet的详细步骤。 二、系统要求 在开始安装之前&#xff0…

zookeeper-docker版

Zookeeper-docker版 1 zookeeper概述 1.1 什么是zookeeper Zookeeper是一个分布式的、高性能的、开源的分布式系统的协调&#xff08;Coordination&#xff09;服务&#xff0c;它是一个为分布式应用提供一致性服务的软件。 1.2 zookeeper应用场景 zookeeper是一个经典的分…

StableDiffusion本地部署 3 整合包猜想

本地部署和整合包制作猜测 文章目录 本地部署和整合包制作猜测官方部署第一种第二种 StabilityMatrix下载整合包制作流程猜测 写了这么多python打包和本地部署的文章&#xff0c;目的是向做一个小整合包出来&#xff0c;不要求有图形界面&#xff0c;只是希望一键就能运行。 但…

数据结构(初阶)(七)----树和二叉树(前中后序遍历)

实现链式结构的二叉树 实现链式结构的二叉树遍历前序遍历中序遍历后序遍历 节点个数叶子节点个数⼆叉树第k层结点个数⼆叉树的深度/⾼度查找值为X的节点二叉树的销毁 层序遍历判断二叉树是否为完全二叉树 ⽤链表来表⽰⼀棵⼆叉树&#xff0c;即⽤链来指⽰元素的逻辑关系。 通常…

科技赋能筑未来 中建海龙MiC建筑技术打造保障房建设新标杆

近日&#xff0c;深圳梅林路6号保障房项目顺利封顶&#xff0c;标志着国内装配式建筑领域又一里程碑式突破。中建海龙科技有限公司&#xff08;以下简称“中建海龙”&#xff09;以模块化集成建筑&#xff08;MiC&#xff09;技术为核心&#xff0c;通过科技创新与工业化建造深…

json介绍、python数据和json数据的相互转换

目录 一 json介绍 json是什么&#xff1f; 用处 Json 和 XML 对比 各语言对Json的支持情况 Json规范详解 二 python数据和json数据的相互转换 dumps() : 转换成json loads(): 转换成python数据 总结 一 json介绍 json是什么&#xff1f; 实质上是一条字符串 是一种…

计算机毕设JAVA——某高校宿舍管理系统(基于SpringBoot+Vue前后端分离的项目)

文章目录 概要项目演示图片系统架构技术运行环境系统功能简介 概要 网络上许多计算机毕设项目开发前端界面设计复杂、不美观&#xff0c;而且功能结构十分单一&#xff0c;存在很多雷同的项目&#xff1a;不同的项目基本上就是套用固定模板&#xff0c;换个颜色、改个文字&…

Spring Boot 测试:单元、集成与契约测试全解析

一、Spring Boot 分层测试策略 Spring Boot 应用采用经典的分层架构&#xff0c;不同层级的功能模块对应不同的测试策略&#xff0c;以确保代码质量和系统稳定性。 Spring Boot 分层架构&#xff1a; Spring Boot分层架构 A[客户端] -->|HTTP 请求| B[Controller 层] …

Oracle 数据库基础入门(四):分组与联表查询的深度探索(上)

在 Oracle 数据库的学习进程中&#xff0c;分组查询与联表查询是进阶阶段的重要知识点&#xff0c;它们如同数据库操作的魔法棒&#xff0c;能够从复杂的数据中挖掘出有价值的信息。对于 Java 全栈开发者而言&#xff0c;掌握这些技能不仅有助于高效地处理数据库数据&#xff0…

机器学习的起点:线性回归Linear Regression

机器学习的起点&#xff1a;线性回归Linear Regression 作为机器学习的起点&#xff0c;线性回归是理解算法逻辑的绝佳入口。我们从定义、评估方法、应用场景到局限性&#xff0c;用生活化的案例和数学直觉为你构建知识框架。 回归算法 一、线性回归的定义与核心原理 定义&a…

17、什么是智能指针,C++有哪几种智能指针【高频】

智能指针其实不是指针&#xff0c;而是一个&#xff08;模板&#xff09;类&#xff0c;用来存储指向某块资源的指针&#xff0c;并自动释放这块资源&#xff0c;从而解决内存泄漏问题。主要有以下四种&#xff1a; auto_ptr 它的思想就是当当一个指针对象赋值给另一个指针对…

PyCharm接入本地部署DeepSeek 实现AI编程!【支持windows与linux】

今天尝试在pycharm上接入了本地部署的deepseek&#xff0c;实现了AI编程&#xff0c;体验还是很棒的。下面详细叙述整个安装过程。 本次搭建的框架组合是 DeepSeek-r1:1.5b/7b Pycharm专业版或者社区版 Proxy AI&#xff08;CodeGPT&#xff09; 首先了解不同版本的deepsee…

PyCharm怎么集成DeepSeek

PyCharm怎么集成DeepSeek 在PyCharm中集成DeepSeek等大语言模型(LLM)可以借助一些插件或通过代码调用API的方式实现,以下为你详细介绍两种方法: 方法一:使用JetBrains AI插件(若支持DeepSeek) JetBrains推出了AI插件来集成大语言模型,不过截至2024年7月,官方插件主要…

【定昌Linux系统】部署了java程序,设置开启启动

将代码上传到相应的目录&#xff0c;并且配置了一个.sh的启动脚本文件 文件内容&#xff1a; #!/bin/bash# 指定JAR文件的路径&#xff08;如果JAR文件在当前目录&#xff0c;可以直接使用文件名&#xff09; JAR_FILE"/usr/local/java/xs_luruan_client/lib/xs_luruan_…

Java零基础入门笔记:(7)异常

前言 本笔记是学习狂神的java教程&#xff0c;建议配合视频&#xff0c;学习体验更佳。 【狂神说Java】Java零基础学习视频通俗易懂_哔哩哔哩_bilibili 第1-2章&#xff1a;Java零基础入门笔记&#xff1a;(1-2)入门&#xff08;简介、基础知识&#xff09;-CSDN博客 第3章…