能省一点是一点 - 享元模式(Flyweight Pattern)

news2024/12/27 7:23:09

享元模式(Flyweight Pattern)

  • 享元模式(Flyweight Pattern)
    • 享元模式(Flyweight Pattern)概述
      • 享元模式包含的角色:
      • 享元模式应用场景
    • talk is cheap, show you my code
    • 总结

享元模式(Flyweight Pattern)

享元模式(Flyweight Pattern)是一种结构型设计模式,它主要用于减少创建大量细粒度对象所带来的内存占用问题。通过共享尽可能多的对象,即所谓的“享元”,来减少内存使用量和提高性能。这种设计模式特别适合于需要大量创建相同对象的情况。而且不要被享元这个名称迷惑,Flyweight的意思是轻量级的意思,更多的意思,这个模式是想告诉共享内存对象这个意思。

为什么会有这种设计模式
比如,当我们要构建的系统中有大量基本一样的元素的时候。
在这里插入图片描述
小时候我们玩过的像素风的游戏,大家可以看到实际上里面的各种场景就是有大量的基础元素拼装出来的。有很多完全一样的像素块,那对这些像素块,我们不需要每次用的时候都创建新的像素块对象。因为新建新的对象,需要消耗堆内存,而且这种消耗是没有意义的。

享元模式(Flyweight Pattern)概述

当一个软件需要创建大量的对象的时候,就会导致内存消耗过多,系统性能下降。而享元模式就是为了解决这个问题而出现的设计模式。

享元模式(Flyweight Pattern)的核心思想: 如果一个对象实例创建之后不可变的话,反复创建这种实例就变得没有必要,直接向客户端返回一个共享的实例就可以了,这样既节省了内存,还避免了创建对象的过程,提升运行效率。

享元模式包含的角色:

享元模式主要包含以下四种角色

  • 抽象享元(Flyweight)角色:是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
  • 具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。
  • 非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
  • 享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检查系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
    在这里插入图片描述

享元模式应用场景

应用场景其实是围绕着享元模式的核心设计思想,减少对象的创建展开的。大致有下面几种:

  1. 软件设计中有大量相似的对象
  2. 缓存场景
  3. 需要多次重复使用某一个对象的时候

talk is cheap, show you my code

在这里插入图片描述
我们设计围棋的时候,会发现,白棋和黑棋会有很多,但是它们都是一样的。所以我们通过利用享元模式来设计创建围棋中的棋子。

围棋棋子 Go chess pieces

public class GoChessPiecesFactory {
    public static Map<String, AbstractGoChessPieces> map = new HashMap<>();

    public static AbstractGoChessPieces getAbstractGoChessPieces(String color) {
        if (map.containsKey(color)) {
            return map.get(color);
        }else {
            if (color.equals("black")) {
                AbstractGoChessPieces black = new BlackGoChessPieces();
                map.put("black", black);
            }
            if (color.equals("white")) {
                AbstractGoChessPieces white = new WhiteGoChessPieces();
                map.put("white", white);
            }
        }
        return map.getOrDefault(color, null);
    }
}

abstract class  AbstractGoChessPieces {
    String color;

    public abstract void display();

}

class BlackGoChessPieces extends AbstractGoChessPieces {

    @Override
    public void display() {
        System.out.println("black");
    }
}

class WhiteGoChessPieces extends AbstractGoChessPieces {

    @Override
    public void display() {
        System.out.println("white");
    }
}

public class Test4 {
    public static void main(String[] args) {
        AbstractGoChessPieces black = GoChessPiecesFactory.getAbstractGoChessPieces("black");
        AbstractGoChessPieces black1 = GoChessPiecesFactory.getAbstractGoChessPieces("black");
        AbstractGoChessPieces black2 = GoChessPiecesFactory.getAbstractGoChessPieces("black");
        AbstractGoChessPieces white = GoChessPiecesFactory.getAbstractGoChessPieces("white");
        AbstractGoChessPieces white1 = GoChessPiecesFactory.getAbstractGoChessPieces("white");
        System.out.println(black == black1);
        System.out.println(black1 == black2);
        System.out.println(white == white1);

        black.display();
        white.display();
    }

}

输出结果

true
true
true
black
white

代码解释:

  1. AbstractGoChessPieces 抽象类 : 定义了一个抽象类 AbstractGoChessPieces,表示围棋棋子的基本属性和行为。
  2. BlackGoChessPieces 类 :继承自 AbstractGoChessPieces,表示黑色棋子。
  3. WhiteGoChessPieces 类 : 继承自 AbstractGoChessPieces,表示白色棋子。
  4. GoChessPiecesFactory 类 :工厂类 GoChessPiecesFactory 负责创建并缓存 AbstractGoChessPieces 的实例。

总结

当代码实现中出现大量相同对象的时候,我们就可以考虑使用享元模式。这种设计模式通过共享对象,节约了内存空间,提升了系统性能。
优点:

  1. 减少内存中的对象数量
  2. 享元模式外部状态不影响内部状态
    缺点:
  3. 享元模式需要隔离出内外两种状态,会使得代码逻辑变得复杂一点

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

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

相关文章

学习C++:变量

变量&#xff1a; 作用&#xff1a;给一段指定的内存空间起名&#xff0c;方便操作这段内容 &#xff08;变量存在的意义&#xff1a;方便我们管理内存空间&#xff09; 语法&#xff1a;数据类型 变量名 初始值&#xff1b; 实例&#xff1a;

蓝桥杯物联网开发板硬件组成

第一节 开发板简介 物联网设计与开发竞赛实训平台由蓝桥杯大赛技术支持单位北京四梯科技有限公司设计和生产&#xff0c;该产品可用于参加蓝桥杯物联网设计与开发赛道的竞赛实训或院校相关课程的 实践教学环节。 开发板基于STM32WLE5无线微控制器设计&#xff0c;芯片提供了25…

Day35汉明距离

两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。 给你两个整数 x 和 y&#xff0c;计算并返回它们之间的汉明距离。 class Solution {public int hammingDistance(int x, int y) {int cnt 0;while (Math.max(x, y) ! 0) {if ((x & 1) ! (y &…

matplotlib pyton 如何画柱状图,利用kimi,直接把图拉倒上面,让他生成

要绘制类似于您提供的图像的柱状图&#xff0c;您可以使用Python中的Matplotlib库&#xff0c;这是一个非常流行的绘图库。以下是一个简单的示例代码&#xff0c;展示如何使用Matplotlib来创建一个类似的柱状图&#xff1a; python import matplotlib.pyplot as plt import nu…

计算机网络——期末复习(3)4-6章考试重点

第四章 根据IPv4第1个十进制数值判断&#xff0c;127以下为A类&#xff0c;128~191为B类&#xff0c;192~223为C类不能分配给主机或路由器接口的&#xff1a;A类网络号0和127&#xff0c;主机号全为0或全为1私有地址&#xff08;Private IP Address&#xff09;是指一类专门保…

【安全编码】Web平台如何设计防止重放攻击

我们先来做一道关于防重放的题&#xff0c;答案在文末 防止重放攻击最有效的方法是&#xff08; &#xff09;。 A.对用户密码进行加密存储使用 B.使用一次一密的加密方式 C.强制用户经常修改用户密码 D.强制用户设置复杂度高的密码 如果这道题目自己拿不准&#xff0c;或者…

【WebAR-图像跟踪】在Unity中基于Imagine WebAR实现AR图像识别

写在前面的话 感慨一下&#xff0c; WebXR的发展是真的快&#xff0c;20年的时候&#xff0c;大多都在用AR.js做WebAR。随着WebXR标准发展&#xff0c;现在诸如Threejs、AFrame、Unity等多个平台都支持里WebXR。 本文将介绍在Unity中使用 Image Tracker实现Web端的AR图像识别功…

HTML5实现好看的圣诞节网站源码

HTML5实现好看的圣诞节网站源码 前言一、设计来源1.1 主界面1.2 圣诞节由来界面1.3 圣诞活动界面1.4 圣诞活动门票界面1.5 团队介绍界面1.6 圣诞照片墙界面1.7 圣诞留言界面1.8 圣诞趣事界面1.9 联系我们界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 HTML5实现好…

go下载依赖提示连接失败

1、现象 Go下载模块提示连接失败 dial tcp 142.251.42.241:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.…

分布式事务入门 一

分布式事务入门 一 您好&#xff0c;我是今夜写代码,今天学习下分布式事务相关理论&#xff0c;以及常见的解决方案&#xff0c;为后续掌握Seata分布式事务框奠定基础。 为什么需要分布式事务? 分布式事务主要由于存储资源的分布性&#xff0c;通常涉及多个数据库。 分布式…

VSCode设置Playwright教程

1.安装扩展 打开VS Code&#xff0c;在扩展—>搜索"Playwright Test for VSCode"&#xff0c;点击安装 按快捷键CommandShiftP&#xff0c;输入install playwright&#xff0c;点击安装Playwright 安装成功会有如下提示 2.调试脚本 打开tests/example.spec.ts文…

在一个C工程文件中,如果一个函数要引用另一个文件中的函数,并不是用extern进行声明,而是在包含的头文件中进行声明

在C语言的某个工程中&#xff0c;一个不是主函数的函数如果引用另一个文件中的某个函数&#xff0c;是不是要先用extern引入&#xff1f;比如下面的代码&#xff1a; void DisplayInit(void) {extern void FramebufferInit(void);FramebufferInit(); }在C语言中&#xff0c;不…

Qt天气预报系统设计_更改窗口名称和图标

Qt 天气预报系统 1、更改窗口名称2、更改窗口图标2.1先把资源加入项目2.2选择资源文件更改窗口图标 1、更改窗口名称 更改MainWindow下的windowTitle即可 2、更改窗口图标 2.1先把资源加入项目 右键项目文件夹&#xff0c;选择 Add New... 选择Qt&#xff0c;接着选择 Qt …

数据仓库工具箱—读书笔记02(Kimball维度建模技术概述04、使用一致性维度集成)

Kimball维度建模技术概述 记录一下读《数据仓库工具箱》时的思考&#xff0c;摘录一些书中关于维度建模比较重要的思想与大家分享&#x1f923;&#x1f923;&#x1f923; 第二章前言部分作者提到&#xff1a;技术的介绍应该通过涵盖各种行业的熟悉的用例展开&#xff08;赞同…

Matlab 和 R 语言的数组索引都是从 1 开始,并且是左闭右闭的

文章目录 一、前言二、主要内容三、小结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 在早期的计算机科学中&#xff0c;数组索引从 1 开始是很常见的。例如&#xff0c;Fortran 和 Pascal 等编程语言也采用了从 1 开始的索引。 这种索引…

Redis - Token JWT 概念解析及双token实现分布式session存储实战

Token 定义&#xff1a;令牌&#xff0c;访问资源接口&#xff08;API&#xff09;时所需要的资源凭证 一、Access Token 定义&#xff1a;访问资源接口&#xff08;API&#xff09;时所需要的资源凭证&#xff0c;存储在客户端 组成 组成部分说明uid用户唯一的身份标识time…

vue3使用video-player实现视频播放(可拖动视频窗口、调整大小)

1.安装video-player npm install video.js videojs-player/vue --save在main.js中配置全局引入 // 导入视频播放组件 import VueVideoPlayer from videojs-player/vue import video.js/dist/video-js.cssconst app createApp(App) // 视频播放组件 app.use(VueVideoPlayer)2…

数据库MySQL(1)

一、数据库简介 数据库是一类软件&#xff0c;其作用就是更加高效的组织数据&#xff0c;我们要讲的数据库软件是MySQL&#xff0c;MySQL所使用的是sql语句&#xff0c;SQL语句就是专门操作数据库的编程语言 数据库组织形式为&#xff1a;数据库→表→行→列 每一个数据库里…

启动动效流程梳理(二)

performSurfacePlacementNoTrace() 这一段从performSurfacePlacement()开始讲起&#xff0c;因为在trace中可以看到在SystemServer中&#xff0c;动效会从performSurfacePlacement这个tag点触发。这里的流程就是在窗口状态改变之后&#xff0c;会触发performSurfacePlacement流…

js-000000000000

1、js书写的位置 - 内部 <body> <!-- 习惯把 js 放到 /body 的后面 --> <script> console.log(这是内部 js 的书写位置) alert(内部js) </script> </body> <body><!-- 习惯把 js 放到 /body 的后面 --><script>console.log(这…