11、设计模式之享元模式(Flyweight)

news2024/11/15 19:46:42

一、什么是享元模式
享元模式是一种结构型的设计模式。它的主要目的是通过共享对象来减少系统种对象的数量,其本质就是缓存共享对象,降低内存消耗。

享元模式将需要重复使用的对象分为两个部分:内部状态和外部状态。

内部状态是不会变化的,可以被多个对象共享,而外部状态会随着对象的使用而改变。比如,连接池中的连接对象,保存在连接对象中的用户名、密码、连接URL等信息,在创建对象的时候就设置好了,不会随环境的改变而改变,这些为内部状态。而当每个连接要被回收利用时,我们需要将它标记为可用状态,这些为外部状态。

二、 角色组成
抽象享元角色(FlyWeight):享元对象抽象基类或者接口,同时定义出对象的外部状态和内部状态的接口或实现;
具体享元角色(ConcreteFlyWeight):实现抽象享元类中的方法,是需要共享的对象类
享元工厂(FlyWeightFactory):维护一个享元对象的池,内部使用一个 Map 存储已经创建的享元对象
三、优缺点
优点:

共享大量相似对象,可以避免大量无谓的内存分配和释放操作,缓解垃圾回收器的压力,提高吞吐量。
避免对象的重复创建,尤其是在创建大量具有相同属性的对象时,使用享元模式可以大大提高系统的性能和效率,避免出现大量的重复对象占用内存空间,降低系统开销。
享元模式的内部状态和外部状态是分离的,内部状态存储在内存中,外部状态可以根据需要进行传递,这样可以有效地降低对象间的耦合度。
共享的对象能够在多个线程中安全地共享并发访问,不会有线程安全问题。
缺点:

实现比较复杂。在实际开发中,需要对内部状态和外部状态进行较为繁琐的区分。
过度共享。如果对象的内部和外部状态没有分清,或者没有合理地设计,可能会导致系统过度共享,导致共享的对象过多。
增加代码的复杂度。程序员必须时刻根据系统的实际情况以及内部状态和外部状态的不同选择使用对象池或享元工厂来管理内存和共享对象,进一步增加了系统的复杂度。
四、应用场景
4.1 生活场景
共享单车:在共享单车系统中,每辆车可以看做是一个享元对象。共享的部分是单车的基本属性,比如颜色、价格、型号等。相同型号、价格、颜色的单车可以共享同一个对象,不需要每次创建新的对象。
车票预订:在一个车站的车票预订系统中,有许多订票窗口,每个窗口可以处理多个订票请求。每个订票请求都可以看作一个享元对象,而订票窗口可以看作是“享元工厂”。订票窗口根据请求的参数来创建或共享对象,避免创建过多的重复对象,提高了系统的性能。
汉字输入法:在汉字输入法中,由于汉字数量很多,为了避免重复创建,使用享元模式,即相同的汉字只需要在内存中创建一次,这样就大大减少了内存的消耗,也加快了输入法的执行速度。
4.2 java场景
String 类型:内部维护了一个字符串对象池(即字符串常量池),相同的字符串只会在池中创建一次,之后它们会被多个对象共享,这样可以减少字符串对象的数量,降低内存的使用,并提升系统的效率。
Integer 类型:对常用的整数值(-127~128)进行了缓存,避免了每次创建新的 Integer 对象,提高了系统的性能。
数据库连接池:数据库连接是非常消耗资源的,通过享元模式将连接池内部的连接对象进行复用,减少连接对象的创建和销毁,提高系统的效率和性能。
线程池:通过享元模式将线程池中创建的线程对象进行复用,减少了线程的创建和销毁,从而提高系统的性能。
五、代码实现
下面以共享单车为例,解释一下享元模式。每一辆车可以看做是一个享元对象,共享的部分为颜色和价格。

抽象享元角色:Bike
具体享元角色:Mobike、MTBike
享元工厂:BikeFactory

5.0 UML类图
在这里插入图片描述

5.1 Bike——抽象享元类(FlyWeight)

/**
 * 
 * 1.抽象享元类(FlyWeight):单车
 * 单车有很多共同的信息比如:价格、颜色
 */
public abstract class Bike {
 
    protected String color;
 
    protected int price;
 
    public Bike(String color,int price){
        this.color=color;
        this.price=price;
    }
 
    //展示单车信息
    public abstract void show();
 

}
5.2 具体享元类(ConcreteFlyWeight)

/**
 * 
 * 2.具体享元类(ConcreteFlyWeight):摩拜单车
 */
public class Mobike extends Bike{
 
    public Mobike(String color,int price){
        super(color,price);
    }
 
    @Override
    public void show() {
        System.out.println("生产成功:摩拜单车——"+color+","+"起步价"+price+"元");
    }
}
/**
 * 
 * 2.具体享元类(ConcreteFlyWeight):美团单车
 */
public class MTBike extends Bike{
 
    public MTBike(String color,int price){
        super(color,price);
    }
 
    @Override
    public void show() {
        System.out.println("生产成功:小黄车——"+color+","+"起步价"+price+"元");
    }
}

5.3 BikeFactory——享元工厂(FlyWeightFactory)

/**
 * 
 * 3.享元工厂类(FlyWeightFactory):单车工厂
 */
public class BikeFactory {
    //map缓存
    public static Map<String,Bike> bikeMap=new HashMap<>();
    public static Bike getBike(String color,String type){
        String key=color+"_"+type;
        if(bikeMap.containsKey(key)){
            //如果已经有该颜色和类型的单车,直接返回
            return bikeMap.get(key);
        }else {
            Bike bike=null;
            //没有,创建并放入缓存
            if("mobike".equals(type)){
                bike=new Mobike(color,1);
            }else if ("MT".equals(type)){
                bike=new MTBike(color,2);
            }else {
                System.out.println("抛异常!没有该类型的单车");
            }
            //放入缓存
            bikeMap.put(key,bike);
            return bike;
        }
    }
}

5.4 testFlyWeight

/**
 * 
 * 享元模式测试类
 */
@SpringBootTest
public class TestFlyweight {
    @Test
    void testFlyweight(){
        //摩拜单车
        Bike bike1 = BikeFactory.getBike("黑色", "mobike");
        //美团单车
        Bike bike2 = BikeFactory.getBike("黑色", "MT");
        bike1.show();
        bike2.show();
        System.out.println("总共有"+BikeFactory.bikeMap.size()+"种类型单车");
 
        System.out.println("--------创建相同类型和颜色的单车----------");
        Bike bike3 = BikeFactory.getBike("黑色", "mobike");
        bike3.show();
        //再次看有多少类型
        System.out.println("总共有"+BikeFactory.bikeMap.size()+"种类型单车");
    }
}

在这里插入图片描述

六、总结
享元模式其实就是工厂模式的一个改进机制,享元模式同样要求创建一个或一组对象,并且就是通过工厂方法生成对象的,不同的地方在于享元模式增加了缓存的功能。

主要的使用场景:

当程序中需要创建大量的相似对象时,可以使用享元模式来共享相同的内部状态,减少对象的重复创建,节省内存开销。
当系统运行效率较低,存在大量的内存开销时,可以采用享元模式来优化内存使用,加快程序的执行速度。
当系统中的对象访问比较频繁时,可以使用享元模式来优化系统性能,减少重复对象的创建和销毁,提高程序的运行效率。
当系统中需要共享一些公共对象或静态数据时,可以使用享元模式来降低系统的开销,提升系统的性能。
当系统需要考虑加强安全控制时,可以使用享元模式来保证对对象访问的控制,实现权限控制、缓存控制等功能。
从上述不难看出,享元模式适用于需要创建大量相似的对象以及共享公共信息的场景,同时也适用于需要考虑性能优化和共享控制的系统。但是使用之前一定要考虑清楚,还是那句话,不要为了使用设计模式而去使用设计模式。

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

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

相关文章

进电子厂了,感触颇多...

作者&#xff1a;三哥 个人网站&#xff1a;https://j3code.cn 本文已收录到语雀&#xff1a;https://www.yuque.com/j3code/me-public-note/lpgzm6y2nv9iw8ec 是的&#xff0c;真进电子厂了&#xff0c;但主人公不是我。 虽然我不是主人公&#xff0c;但是我经历的过程是和主…

【2024-03-12】设计模式之模板模式的理解

实际应用场景&#xff1a;制作月饼 过程描述&#xff1a; 一开始&#xff0c;由人工制作月饼&#xff0c; 第一个&#xff1a;根据脑子里面月饼的形状&#xff0c;先涅出月饼的形状&#xff0c;然后放入面粉和馅料把开口合并起来。 第二个&#xff1a;根据脑子里面月饼的形状&…

短剧小程序系统:打造沉浸式短剧体验,开启短剧新纪元

随着移动互联网的迅猛发展&#xff0c;短剧作为一种新兴的内容形式&#xff0c;正逐渐受到广大用户的喜爱和追捧。为了满足用户对短剧内容的需求和观看体验的提升&#xff0c;短剧小程序系统应运而生&#xff0c;为用户带来了更加便捷、沉浸式的短剧观看体验。 短剧小程序系统…

如何在Linux本地搭建Tale网站并实现无公网ip远程访问

文章目录 前言1. Tale网站搭建1.1 检查本地环境1.2 部署Tale个人博客系统1.3 启动Tale服务1.4 访问博客地址 2. Linux安装Cpolar内网穿透3. 创建Tale博客公网地址4. 使用公网地址访问Tale 前言 今天给大家带来一款基于 Java 语言的轻量级博客开源项目——Tale&#xff0c;Tale…

【Python】科研代码学习:八 FineTune PretrainedModel (用 trainer,用 script);LLM文本生成

【Python】科研代码学习&#xff1a;八 FineTune PretrainedModel [用 trainer&#xff0c;用 script] LLM文本生成 自己整理的 HF 库的核心关系图用 trainer 来微调一个预训练模型用 script 来做训练任务使用 LLM 做生成任务可能犯的错误&#xff0c;以及解决措施 自己整理的 …

8块硬盘故障的存储异常恢复案例一则

关键词 华为存储、硬盘域、LUN热备冗余、重构、预拷贝 oracle rac、多路径 There are many things that can not be broken&#xff01; 如果觉得本文对你有帮助&#xff0c;欢迎点赞、收藏、评论&#xff01; 一、问题现象 近期遇到的一个案例&#xff0c;现象是一套oracl…

PXI8540高速数据采集卡

XI高速数据采集卡&#xff0c;PXI8540卡是一种基于PXI总线的模块化仪器&#xff0c;可使用PXI系统&#xff0c;在一个机箱内实现一个综合的测试系统&#xff0c;构成实验室、产品质量检测中心等各种领域的数据采集、波形分析和处理系统。也可构成工业生产过程监控系统。它的主要…

ThreeWayBranch 优化阅读笔记

1. 优化目的 通过重排三分支的 BB 块减少比较指令的执行次数 代码路径: bolt/lib/Passes/ThreeWayBranch.cpp2. 效果 优化前&#xff1a; 注&#xff1a; 黄色数字表示BB块编号&#xff0c; 紫色表示该分支跳转的次数&#xff0c;绿色是代码里BB块的变量名 ThreeWayBranc…

P6327 区间加区间 sin 和 (线段树+数学)

传送门https://www.luogu.com.cn/problem/P6327 比较板子的一题&#xff0c;主要考察公式 //sin(ax)sinxcosasinacosx //cos(ax)cosacosx-sinasinx 直接贴代码吧 // Problem: // P6327 区间加区间 sin 和 // // Contest: Luogu // URL: https://www.luogu.com.cn/pr…

@Conditional注解详解

目录 一、Conditional注解作用 二、Conditional源码解析 2.1 Conditional源码 2.2 Condition源码 三、Conditional案例 3.1 Conditional作用在类上案例 3.1.1 配置文件 3.1.2 Condition实现类 3.1.3 Bean内容类 3.1.4 Config类 3.1.5 Controller类 3.1.6 测试结果 3…

ChatGPT GPT4科研应用、数据分析与机器学习、论文高效写作、AI绘图技术

原文链接&#xff1a;ChatGPT GPT4科研应用、数据分析与机器学习、论文高效写作、AI绘图技术https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247596849&idx3&sn111d68286f9752008bca95a5ec575bb3&chksmfa823ad6cdf5b3c0c446eceb5cf29cccc3161d746bdd9f2…

Lim接口测试平台开展自动化的优势

一、数据对比 使用Lim接口测试平台后&#xff0c;相比以往采用Postman或excel关键字驱动带来的效率提升&#xff1a; 编写效率提升300%&#xff0c;原来10个步骤的用例&#xff0c;一个工作日调试编写只能输出6条&#xff0c;现在一天能输出18条。维护成本复杂度降低100%&…

Vue3.0里为什么要用 Proxy API 替代 defineProperty API

一、Object.defineProperty 定义&#xff1a;Object.defineProperty() 方法会直接在一个对象上定义一个新属性&#xff0c;或者修改一个对象的现有属性&#xff0c;并返回此对象 为什么能实现响应式 通过defineProperty 两个属性&#xff0c;get及set get 属性的 getter 函…

北斗卫星助力海上风电厂:打造海上绿色能源新时代

北斗卫星助力海上风电厂&#xff1a;打造海上绿色能源新时代 近日&#xff0c;东海航海保障中心温州航标处在华能苍南海上风电场完成首套北斗水上智能感知综合预警系统现场安装调试工作&#xff0c;经现场效能测定&#xff0c;能有效保障海上风电场运行安全和海域船舶通航安全…

华为OD机试 - 模拟数据序列化传输(Java JS Python C C++)

题目描述 模拟一套简化的序列化传输方式,请实现下面的数据编码与解码过程 编码前数据格式为 [位置,类型,值],多个数据的时候用逗号分隔,位置仅支持数字,不考虑重复等场景;类型仅支持:Integer / String / Compose(Compose的数据类型表示该存储的数据也需要编码)编码后数…

光电容积脉搏波PPG信号分析笔记

1.脉搏波信号的PRV分析 各类分析参数记参数 意义 公式 参数意义 线性分析 时域分析 均值MEAN 反应RR间期的平均水平 总体标准差SDNN 评估24小时长程HRV的总体变化&#xff0c; SDNN &#xff1c; 50ms 为异常&#xff0c;SDNN&#xff1e;100ms 为正常&#xff1b;…

如何解决爬虫程序访问速度受限问题

目录 前言 一、代理IP的获取 1. 自建代理IP池 2. 购买付费代理IP 3. 使用免费代理IP网站 二、代理IP的验证 三、使用代理IP进行爬取 四、常见问题和解决方法 1. 代理IP不可用 2. 代理IP速度慢 3. 代理IP被封禁 总结 前言 解决爬虫程序访问速度受限问题的一种常用方…

群晖部署私人聊天服务器Vocechat并结合内网穿透实现公网远程访问

文章目录 1. 拉取Vocechat2. 运行Vocechat3. 本地局域网访问4. 群晖安装Cpolar5. 配置公网地址6. 公网访问小结 7. 固定公网地址 如何拥有自己的一个聊天软件服务? 本例介绍一个自己本地即可搭建的聊天工具,不仅轻量,占用小,且功能也停强大,它就是Vocechat. Vocechat是一套支持…

怎么把视频变成gif动图?一招在线生成gif动画

MP4是一种常见的视频文件格式&#xff0c;它是一种数字多媒体容器格式&#xff0c;可以用于存储视频、音频和字幕等多种媒体数据。MP4格式通常用于在计算机、移动设备和互联网上播放和共享视频内容。要将MP4视频转换为GIF格式&#xff0c;您可以使用专门的视频转gif工具。这个工…