【设计模式】结构型-享元模式

news2024/11/30 11:45:09

在浮华世界中,享元犹如静水深流,细品每一片风景,留下岁月的深情。

文章目录

  • 一、内存溢出问题
  • 二、享元模式
  • 三、享元模式的核心组成
  • 四、运用享元模式
  • 五、享元模式的应用场景
  • 六、小结
  • 推荐阅读

一、内存溢出问题

class Circle {
    private String color;

    public Circle(String color) {
        this.color = color;
    }

    public void draw() {
        System.out.println("Drawing a " + color + " circle.");
    }
}

public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 1000000; i++) {
            Circle circle = new Circle("red");
            circle.draw();
        }
    }
}

在上面的例子中,我们创建了一百万个红色的 Circle 对象。每个对象都有自己的内存空间,这会消耗大量的内存。如果我们需要更多的 Circle 对象,或者 Circle 对象的大小更大,那么内存消耗将会更严重。

二、享元模式

享元模式是一种结构型设计模式,旨在通过共享尽可能多的对象来减少内存使用和提高性能。在享元模式中,对象被分为内部状态和外部状态。内部状态是可以共享的,而外部状态则取决于对象的上下文,因此不能共享。享元模式通过共享内部状态来减少相似对象的数量,从而节省内存。

例如,考虑一个文字处理应用程序,用户在文档中使用了大量相同的字体和字号的文字。在享元模式中,字体和字号可以作为内部状态,而文字内容则是外部状态。这样,如果多个文字具有相同的字体和字号,它们可以共享同一个字体对象,从而节省内存。

三、享元模式的核心组成

享元模式的核心组件主要包括以下几个部分:

  1. Flyweight(享元接口):这是享元模式的核心接口,用于定义共享对象的方法。
  2. ConcreteFlyweight(具体享元类):这是享元接口的实现类,用于实现共享对象的方法。
  3. FlyweightFactory(享元工厂类):这是享元模式的关键组件,负责创建和管理享元对象。享元工厂类通常包含一个池(缓存)用于存储和复用已经创建的享元对象。

在这里插入图片描述

在这个类图中:

  1. Flyweight 是享元接口,定义了享元对象的方法。
  2. ConcreteFlyweight 是具体享元类,实现了享元接口。
  3. UnsharedConcreteFlyweight 是不共享的具体享元类,它也实现了享元接口,但不被享元工厂所共享。
  4. FlyweightFactory 是享元工厂类,负责创建和管理享元对象。它包含一个 flyweights 字段,这是一个映射,用于存储和复用已经创建的享元对象。

四、运用享元模式

场景假设:有一个绘图应用程序,需要绘制大量的圆形。这些圆可能有不同的颜色,但除颜色外,所有的圆都是相同的。

  1. 定义享元接口:首先,我们需要定义一个享元接口,这个接口定义了享元对象的方法。在我们的示例中,我们定义了一个 Circle 接口,它有一个 draw 方法。

    public interface Circle {
        void draw();
    }
    
  2. 创建具体享元类:然后,我们需要创建一个实现享元接口的具体享元类。在我们的示例中,我们创建了一个 ConcreteCircle 类,它实现了 Circle 接口。

    public class ConcreteCircle implements Circle {
        private String color;
    
        public ConcreteCircle(String color) {
            this.color = color;
        }
    
        @Override
        public void draw() {
            System.out.println("Drawing a " + color + " circle.");
        }
    }
    
  3. 创建享元工厂:接下来,我们需要创建一个享元工厂,它负责创建和管理享元对象。在我们的示例中,我们创建了一个 CircleFactory 类,它包含一个 circleMap 字段,这是一个映射,用于存储和复用已经创建的 ConcreteCircle 对象。

    public class CircleFactory {
        private Map<String, Circle> circleMap;
    
        public CircleFactory() {
            circleMap = new HashMap<>();
        }
    
        public Circle getCircle(String color) {
            Circle circle = circleMap.get(color);
    
            if (circle == null) {
                circle = new ConcreteCircle(color);
                circleMap.put(color, circle);
            }
    
            return circle;
        }
    }
    
  4. 使用享元工厂:最后,我们可以使用享元工厂来获取享元对象并使用它们。在我们的示例中,我们使用 CircleFactory 来获取 Circle 对象,并调用它们的 draw 方法。

    public class Main {
        public static void main(String[] args) {
            CircleFactory factory = new CircleFactory();
    
            Circle redCircle = factory.getCircle("red");
            redCircle.draw();
    
            Circle blueCircle = factory.getCircle("blue");
            blueCircle.draw();
    
            Circle redCircle2 = factory.getCircle("red");
            redCircle2.draw();
        }
    }
    

在这个示例中,我们只创建了两个 ConcreteCircle 对象,即使我们调用了三次 getCircle 方法。这是因为当我们第二次请求一个红色的圆时,享元工厂返回了第一次创建的那个红色的圆,而不是创建一个新的对象。

这就是享元模式的优势,它可以通过共享对象来减少内存消耗和提高性能。但是,享元模式也会增加系统的复杂性,因此在使用时需要权衡利弊。

在适合的场景下,享元模式可以带来显著的性能提升。在不适合的场景下,可能会引入不必要的复杂性。所以,我们需要根据实际情况来选择是否使用享元模式。

五、享元模式的应用场景

享元模式适用于以下场景:

  1. 大量相似对象的情况:当系统中存在大量相似对象,且这些对象的区别在于它们的内部状态而不是外部状态时,可以考虑使用享元模式。通过共享内部状态,可以减少对象的数量,从而节省内存。
  2. 对象的数量对系统性能造成影响时:如果系统中创建大量对象会导致内存占用过高或性能下降,可以考虑使用享元模式来共享这些对象,从而减少内存消耗和提高性能。
  3. 多个对象共享相同状态的情况:当多个对象需要共享相同的状态时,可以使用享元模式来避免重复创建这些状态,提高系统的效率。
  4. 对象的外部状态相对较少:如果对象的外部状态相对较少,且可以被抽象出来作为享元对象的外部状态,那么适合使用享元模式。

六、小结

通过使用享元模式,可以有效地减少系统中对象的数量,提高系统的性能和效率。但是,在使用享元模式时需要注意,必须确保共享对象的内部状态是不可变的,否则可能会导致意外的行为。因此,在设计和实现享元模式时,需要谨慎考虑对象的状态管理和共享策略。

在实际项目中,当遇到大量相似对象导致性能问题时,可以考虑使用享元模式来优化内存利用率和提升系统性能,从而更好地满足用户的需求。

推荐阅读

  1. Spring 三级缓存
  2. 深入了解 MyBatis 插件:定制化你的持久层框架
  3. Zookeeper 注册中心:单机部署
  4. 【JavaScript】探索 JavaScript 中的解构赋值
  5. 深入理解 JavaScript 中的 Promise、async 和 await

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

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

相关文章

实现AI口语练习的技术库

国内实现AI口语练习的第三方技术库比较多&#xff0c;以下是一些国内实现AI口语练习的第三方技术库。开发人员可以根据自己的需求选择合适的技术库进行开发。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 讯飞开放平台&#xff1a; …

C++基础7:STL六大组件

目录 一、标准容器 1、顺序容器 vector ​编辑 deque list 容器适配器 stack queue prority_queue: 关联容器 有序关联容器set、mutiset、map、mutimap 增删查O(log n) 无序关联容 unordered_set、unordered_mutiset、unordered_map、unordered_mutimap 增删…

牛客热题:旋转矩阵

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;旋转矩阵题目链接方法一&#x…

Exploring Performance and Cost Optimization with ASIC-Based CXL Memory——论文阅读

EuroSys 2024 Paper CXL论文阅读笔记整理 问题 随着内存密集型应用程序对内存需求的增加&#xff0c;受限于物理限制&#xff0c;如DDR DIMM插槽的可用性和发热问题&#xff0c;以及使用高密度DIMM的成本考虑&#xff0c;现代应用程序的内存需求很容易超过单机的内存容量[2&a…

【教程】使用立创EDA打开JSON格式的PCB及原理图

这里写目录标题 一、将PCB和原理图放同一文件夹二、打开嘉立创EDA并导入.zip文件三、选择.zip文件并选择 “导入文件并提取库” 一、将PCB和原理图放同一文件夹 并打包成.zip文件 二、打开嘉立创EDA并导入.zip文件 嘉立创 我这里用的网页端&#xff0c;客户端下载页面拉到…

大模型应用产品指北

一、试用类型 计算机视觉Computer Vision&#xff1a;Text-to-image(文生图) 二、国内产品 Aliyun通义千问 【体验】 可以替代Stable Diffusion、Midjourney;支持风格、滤镜; [传送门&#xff1a;通义万相] 【体验】Transformer架构&#xff1b;中英双语&#xff1b;开源可以…

疑惑...2024年是不是转行AI产品经理的好时机?

前言 这两年AI突然“火起来” 了 &#xff0c;算是出现了一个“大转折”。 因为就在这2年里&#xff0c;全球所有“大厂”几乎同一时间挤破头在跟进AI技术&#xff0c;从ChatGPT发布&#xff0c;到谷歌、Facebook、亚马逊等都紧跟其后&#xff0c;再到国内百度、腾讯、阿里、…

北斗野外应急呼叫柱:准确定位,一键语音对讲,自定义图传,野外作业安全通信新标杆

在当前云计算、大数据、5G等前沿技术迅猛发展的大背景下&#xff0c;工业控制系统网络化、数字化发展进程的不断深入&#xff0c;其对于工业通讯技术的需求也日益提升&#xff0c;而应急通讯作为工业通讯领域中的一种形式&#xff0c;伴随着国家对其重视程度的加深&#xff0c;…

【数组】【双指针】三数之和

打算冲一把算法类比赛&#xff0c;之前一直对算法提不起兴趣&#xff0c;也有我自己对它的抵触&#xff0c;本身算法也比较菜。 但现在打算勤勤恳恳刷题&#xff0c;踏踏实实总结&#xff0c;冲&#xff01; 数组——双指针 三数之和 该题力扣网址 错误做法 三重循环框架&a…

Windows 11中查找和删除旧文件的几种方法,总有一种适合你

序言 如果你的电脑存储空间不足,最好的办法就是找到并删除旧的、不需要的文件。Windows 11提供了多种方法来查找这些占用存储空间的项目,我们将在本指南中向你展示这些方法以及如何使用它们。 使用存储感知 存储感知是Windows 11的内置功能,可帮助自动清理旧文件。你可以…

2024年第三届数据统计与分析竞赛(B题)数学建模完整思路+完整代码全解全析

你是否在寻找数学建模比赛的突破点&#xff1f;数学建模进阶思路&#xff01; 详细请查 作为经验丰富的数学建模团队&#xff0c;我们将为你带来2024年第三届数据统计与分析竞赛&#xff08;B题&#xff09;的全面解析。这个解决方案包不仅包括完整的代码实现&#xff0c;还有…

宠物空气净化器性能大比拼,美的、希喂、霍尼韦尔哪个牌子最好!

养猫最头疼的就是家里到处都是猫浮毛&#xff0c;铲屎官想家里干净卫生&#xff0c;就得想办法处理好猫浮毛&#xff0c;不及时处理&#xff0c;浮毛长期飘浮在空气中&#xff0c;对铲屎官的身体很容易造成威胁。针对这个问题&#xff0c;使用专门的宠物空气净化器&#xff0c;…

解析Facebook对当代文化传播的影响力

Facebook作为全球最大的社交媒体平台之一&#xff0c;承载着巨大的文化传播功能&#xff0c;对当代文化产生了深远的影响。从社会交流、价值观念到艺术创作和政治动态&#xff0c;Facebook已经成为了人们获取信息、表达观点和交流想法的重要平台。本文将深入解析Facebook对当代…

源代码加密的十个关键点

源代码加密是一种安全措施&#xff0c;其目的是为了保护软件的源代码不被未授权的个人或实体访问或泄露。源代码是软件应用程序的基础&#xff0c;它包含了程序的逻辑结构、核心算法以及设计理念。由于源代码承载了软件的核心知识和创新&#xff0c;因此它具有极高的商业价值和…

C语言—数据在内存中的存储

1.整数在内存中的存储 文章回顾&#xff08;C语言—操作符详解&#xff09; 整数的2进制表示方式有三种&#xff0c;即原码、反码和补码。 有符号的整数&#xff0c;三种表示方式均有符号位和数值位两部分&#xff0c;符号位都是用0表示“正”&#xff0c;用1表示“负”&…

失眠焦虑的饮食小建议

在快节奏的现代生活中&#xff0c;失眠和焦虑已成为许多人的常见问题。除了寻求专业的心理咨询和医疗帮助外&#xff0c;合理的饮食习惯也是缓解这些症状的重要途径。本文将为大家提供一些关于失眠焦虑的饮食小建议&#xff0c;希望能对大家有所帮助。 一、均衡膳食&#xff0c…

Rhinoceros 8 for Mac(犀牛8 mac版) v8.8.24163中文激活版

Rhino 8是一款功能强大的三维构建软件&#xff0c;它可以帮助用户创建各种类型的3D模型&#xff0c;包括产品设计、建筑设计、工业设计计划等。Rhino 7具有直观的界面和丰富的工具库&#xff0c;让用户可以快速轻松地进行建模、编辑、分析和漂染。 Rhino 8支持多种文件格式的导…

期权和股票有什么区别?

今天带你了解期权和股票有什么区别&#xff1f;股票和期权都是投资产品&#xff0c;但它们却是两种截然不同的交易模式&#xff0c;在开户要求上也有很多差别。 期权和股票有什么区别&#xff1f; 权利与义务&#xff1a; 股票&#xff1a;代表公司的所有权的一部分&#xff…

make和Cmake都有什么区别?(内附使用详解)

Make和Cmake make和Cmake的区别&#xff1a; 角色和功能: make: 是一个构建工具&#xff0c;它的任务是读取 Makefile 文件&#xff0c;并基于这些文件中的指令执行具体的构建操作。Makefile 文件包含了如何构建项目的规则&#xff0c;make 负责解析这些规则并执行必要的命令来…

电脑上好用的能够提醒自己的软件有哪些

在繁忙的工作和生活中&#xff0c;我时常感到头脑中的思绪如同乱麻一般&#xff0c;难以理清。会议、项目截止日期、家庭琐事&#xff0c;这些重要的事务有时会在不经意间从我的记忆中溜走。没有一款提醒软件&#xff0c;我仿佛就像是在没有指南针的海洋中漂泊&#xff0c;时常…