设计模式15——享元模式

news2024/11/14 15:11:31

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用,主要是下面的UML图可以起到大作用,在你学习过一遍以后可能会遗忘,忘记了不要紧,只要看一眼UML图就能想起来了。同时也请大家多多指教。

享元模式(Flyweight)

是一种结构型模式。

目录

一、概述

1.1、先给出通用的UML图:

二、举例

2.1、简单举例认识此模式:

2.2、举例:


一、概述

1、运用共享技术有效地支持大量细粒度的对象;
2、享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能够大幅度地减少需要实例化的类的数量。如果能把那些参数转移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目;
3、如果一个应用程序使用大量的对象,而大量的这些对象造成了很大的存储开销时;
4、内部状态存储在享元对象(目标对象)中,它包含了独立于其他对象的信息,这些信息使得享元对象可以被分享;

5、外部状态取决享元对象(目标对象)的所在场景,根据场景而变化,因为是动态变化的所以不能够共享。但有时会根据需要将外部状态传递给享元对象;

6、对象的大多数状态可以是外部状态,如果可以从对象中删除外部状态,那么可以用相对较少的共享对象取代很多组对象;那么此时可以考虑使用享元模式。

(注1:‘粒度’是被用来描述对象大小的。如:我们将 淘宝应用程序 和 购物车功能 看做两个对象,那么我们可以说 淘宝 比起 购物车 粒度要大,或者说 购物车 比起 淘宝 粒度要小)

(注2:享元模式和原型模式都是针对一堆相似类对象。不同的是:享元模式是缩减它们从而减少储存开销;而原型模式是优化它们创建的方式从而减少新增和复制的时间开销。并且两种模式思想完全相反。)

1.1、先给出通用的UML图:

(对模式的简单认识将在下面简单举例认识此模式中说明)

二、举例

2.1、简单举例认识此模式:

2.1.1、假设王五和老刘都要访问博客网站,按照以往的思维,那肯定是要实例化两个博客网站的,如下:

2.1.2、那我们先进行初步的抽象,将博客对象都分为两部分,个人信息和网站功能:

2.1.3、我们可以发现,上述两个博客的实例对象,除了个人信息部分,其他地方都一样,此时我们就可想到享元模式,尝试将个人信息这部分转移出来,也就是将不同的地方拎出来,然后将相同的部分只保留一份:

2.1.4、对比上面两张图可以看到,节省了一个功能部分的存储空间。同理要是有10个人,就会有10个个人信息部分,但功能部分还是只有一份。通过这样的设计就达到了节省空间的目的。也就是把变与不变的地方分开来分析与设计。

此外:

  • 目标对象(享元对象):博客网站
  • 内部状态:功能部分
  • 外部状态:个人信息部分

2.2、举例:

2.2.1、假设现有四个人,张三、李四、王五、老刘,其中张三和李四要访问淘宝,王五和老刘要访问博客,假设淘宝和博客功能一致,那么相比上面的举例,和上述一样将个人信息部分都拎出来,但要注意新加了个淘宝,我们可以得到:

 这次是有两个网站实例淘宝、博客,和四个人的信息部分。再经过分析发现,博客和淘宝可以抽象出:它们都属于网站。这样可以把博客和淘宝当做网站名的外部状态分离出来。

2.2.2、对象之间的关系用UML图表示如下:

(具体的功能部分不是本例的重点,所以就假设淘宝和博客功能部分一样,或者说被抽象出去了)

此例将个人信息单独设计一个类,而淘宝和博客这个就只存储在String字符串中。而实际使用此模式时根据自己的需要可以灵活改变。

2.2.2、Java实现代码如下:

网站抽象类:

abstract class WebSite {
    public abstract void use(User user);
}

具体网站:

public class ConcreteWebSite extends WebSite {
    private String webName;

    public ConcreteWebSite(String webName) {
        this.webName = webName;
    }

    @Override
    public void use(User user) {
        System.out.println("网站名:" + this.webName + ",用户名:" + user.getUserName());
    }
}

网站控制工厂:

public class WebSiteFactory {
    private HashMap<String, WebSite> hashMap = new HashMap<>();

    public WebSite getWebSiteCategory(String key) {
        if (!hashMap.containsKey(key)) {
            hashMap.put(key, new ConcreteWebSite(key));
        }
        return hashMap.get(key);
    }

    public int getWebSiteCount() {
        return hashMap.size();
    }
}

用户:

public class User {
    private String userName;

    public User(String userName) {
        this.userName = userName;
    }

    public String getUserName() {
        return userName;
    }
}

 主程序(发起请求的类):

public class Main {
    public static void main(String[] args) {
        WebSiteFactory webSiteFactory = new WebSiteFactory();

        WebSite webSite1 = webSiteFactory.getWebSiteCategory("淘宝");
        webSite1.use(new User("张三"));

        WebSite webSite2 = webSiteFactory.getWebSiteCategory("淘宝");
        webSite2.use(new User("李四"));

        WebSite webSite3 = webSiteFactory.getWebSiteCategory("博客");
        webSite3.use(new User("王五"));

        WebSite webSite4 = webSiteFactory.getWebSiteCategory("博客");
        webSite4.use(new User("老刘"));

        System.out.println("网站总数为:" + webSiteFactory.getWebSiteCount());
    }
}

这里就不再举例了,可以把上面的Java例子复制到你本地,运行main函数试一下加深理解。这些代码都是我自己学习的时候根据一些教材手敲的,不存在bug可以直接运行。

如果觉得本文还不错,就请点个赞吧!如果有建议,也请评论指教和讨论!

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

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

相关文章

开源金融AI代理平台FinRobot;支持多翻译引擎和模式的高效浏览器翻译开源插件;使用自然语言控制生成视频的通用世界模型

✨ 1: finrobot FinRobot 是一个基于大语言模型的开源金融AI代理平台&#xff0c;适用于多种金融应用。 FinRobot是一个综合性的AI代理平台&#xff0c;超越了原有的FinGPT&#xff0c;旨在满足金融行业的多元化需求。它集成了各种AI技术&#xff0c;不仅仅局限于语言模型&am…

VSCode中snippets(代码模板)的使用

首先安装Vue VSCode Snippets&#xff0c;在组件库中搜索并安装。 然后打开插件文件夹 文件夹名是 "作者名.vscode-插件名-版本号"组成的. C:\Users\Administrator\.vscode\extensions\sdras.vue-vscode-snippets-3.1.1\snippets 打开vue.json "prefix"…

C++系列-定位new表达式(placement-new)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 我们先来强调一个很关键的问题&#xff0c;那就是在new和delete中的一一对应的问题&#xff0c; 我们先来看一段代码&#xff1a; #include<iostream> using namespace …

K8s的CRI机制是什么?

1. 概述 进入 K8s 的世界&#xff0c;会发现有很多方便扩展的 Interface&#xff0c;包括 CRI, CSI, CNI 等&#xff0c;将这些接口抽象出来&#xff0c;是为了更好的提供开放、扩展、规范等能力。 K8s CRI(Container Runtime Interface) 是 K8s 定义的一组与容器运行时进行交…

Web3 游戏周报(5.19 - 5.25)

【5.19 - 5.25】Web3 游戏行业动态&#xff1a; Arbitrum 已开启 “2 亿枚 ARB 游戏催化剂计划”的提案投票。 STEPN 在官方 X 宣布将推出全新社交健身应用 STEPN GO。 Oasys 正式推出《足球小将》漫改 Web3 游戏《Captain Tsubasa-RIVALS-》。 Gala Games &#xff1a;已销…

8.Redis之hash类型

1.hash类型的基本介绍 哈希表[之前学过的所有数据结构中,最最重要的] 1.日常开发中,出场频率非常高. 2.面试中,非常重要的考点, Redis 自身已经是键值对结构了Redis 自身的键值对就是通过 哈希 的方式来组织的 把 key 这一层组织完成之后, 到了 value 这一层~~ value 的其中…

C++容器之向量(std::vector)

目录 1 概述2 使用实例3 接口使用3.1 construct3.2 assigns3.3 iterators3.4 capacity3.5 rezize3.6 reserve3.7 shrink_to_fit3.8 access3.9 assign3.10 push_back3.11 pop_back3.12 insert3.13 erase3.14 swap3.15 clear3.16 emplace3.17 emplace_back3.18 get_allocator1 概…

智慧树下做游戏

游戏开发工程师致力于游戏总体设计 &#xff0c;负责游戏开发工具和运营维护工具的设计与开发 &#xff0c;并配合主程序完成游戏架构及各大功能的设计、开发、调试和其他技术支持 就业方向&#xff1a; 一般有客户端游戏开发和服务器游戏开发 客户端开发&#xff1a; 主要负…

【漏洞复现】Gradio component_server 任意文件读取漏洞(CVE-2024-1561)

0x01 产品简介 Gradi0是一个开源的 Python库&#xff0c;用于创建机器学习模型的交互式界面。它使得展示和测试模型变得简单快捷&#xff0c;无需深入了解复杂的前端技术。广泛应用于数据科学、教育、研究和软件开发领域&#xff0c;尤其适合于快速原型设计、模型验证、演示和…

在没有足够测试数据的请情况下,如何验证前端页面的分页展示和渲染情况

问题描述&#xff1a;测试过程中&#xff0c;为了验证前端页面的展示效果及分页组件的展示情况&#xff0c;测试人员一般都会选择在数据库造数据&#xff0c;但遇到表格管理逻辑特别复杂的情况&#xff0c;可能会耗费大量的时间&#xff0c;此时我们可以选择使用工具模拟返回值…

关于kube-prometheus拉取镜像的问题

由于国内网络环境的问题想通过kube-prometheus配置监控但是拉取镜像会报错 包已经打好下载好镜像就可以使用&#xff1a; https://download.csdn.net/download/m0_59744084/89349768 kubectl get pod -n monitoring 问题&#xff1a;"Failed to pull image "regist…

IC解析之SN74HCS595QPWRQ1

目录 1.主要参数2. 接口定义3. 工作原理分析移位寄存器器的作用SN74HCS595QPWRQ1工作原理 4.总结 1.主要参数 2. 接口定义 其中QH‘为串行输出接口&#xff0c;QA~QH为并行输出接口&#xff0c;SER为串行输入接口&#xff0c;其他未移位以及储存控制引脚 3. 工作原理分析 移位…

26计算机操作系统408考研--操作系统设备管理篇章(五)

文章目录 一、设备是什么&#xff1f;设备管理目标和任务I/O设备分类 二、I/O系统控制方式程序直接控制方式中断控制方式DMA控制方式通道控制方式 I/O软件的组成I/O软件设计目标和原则I/O软件结构设备驱动程序设备无关软件用户层软件用户层的I/O软件 具有通道的设备管理通 道通…

R绘图学习笔记

1、R语言绘制海岸线边界 参考&#xff1a; Drawing beautiful maps programmatically with R, sf and ggplot2 — Part 1: Basics 使用R绘制世界地图及纬度统计图 Drawing maps with R. A basic tutorial&#xff1a;https://dr2blog.hcommons.org/2020/03/23/drawing-maps-wit…

第 52 期:MySQL 半同步复制频繁报错

社区王牌专栏《一问一实验&#xff1a;AI 版》全新改版归来&#xff0c;得到了新老读者们的关注。其中不乏对 ChatDBA 感兴趣的读者前来咨询&#xff0c;表达了想试用体验 ChatDBA 的意愿&#xff0c;对此我们表示感谢 &#x1f91f;。 目前&#xff0c;ChatDBA 还在最后的准备…

keepalived交叉编译

前言 Keepalived可以实现对服务器的健康检查&#xff0c;当主服务器出现故障时&#xff0c;自动将服务切换到备份服务器上&#xff0c;确保服务的连续性&#xff0c;避免单点故障。它还可以管理一个虚拟 IP 地址&#xff0c;在主备服务器之间进行灵活切换&#xff0c;对外提供…

Linux如何在目录下灵活创建、浏览、删除百万个文件

文章目录 一、创建百万级小文件1、单核CPU情况2、多核CPU情况3、执行效率对比3.1、单核的顺序执行3.2、多核的并发执行 二、如何列出/浏览这些文件1、查看目录下文件的数量2、列出&#xff1f;3、ls -f&#xff08;关闭排序功能&#xff09;3.1、执行效率对比 4、通过重定向导入…

2024深圳数字能源展推介会在巴西圣保罗举行

4月26日&#xff0c;深圳市发展和改革委员会在巴西圣保罗国际工程机械及矿山机械展上举行专题推介会&#xff0c;介绍将于今年下半年在深圳市举办的2024国际数字能源展。 深圳市发展和改革委员会主任郭子平在推介会上介绍&#xff0c;为进一步深化数字能源领域互利共赢&#xf…

“二叉堆:不是,啊?”

目录 前言一、堆的概念及结构堆的性质&#xff1a;堆的结构:最大堆最小堆堆顶注意 二、堆的实现1.初始化堆2. 堆的插入什么是堆的向上调整算法&#xff1f; 3.堆的删除什么是堆的向下调整算法&#xff1f; 4.获取堆顶的数据5.获取堆的数据个数6.堆的判空7.堆的销毁 三、建堆的时…

逻辑分析仪的调试使用

调试软件下载&#xff1a;点击跳转 一、接线 逻辑分析仪 设备 GND --- GND CHX&#xff08;数据通道&#xff09; --- 通信引脚 二、数据采集 图中两个可以选择数字大小的地方分别表示 采样深度 &#xff08;10M Samples&a…