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

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

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

内部状态是不会变化的,可以被多个对象共享,而外部状态会随着对象的使用而改变。比如,连接池中的连接对象,保存在连接对象中的用户名、密码、连接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.mfbz.cn/a/450641.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于java+springboot+mybatis+laiyu实现学科竞赛管理系统

基于javaspringbootmybatislaiyu实现学科竞赛管理系统 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获…

UI学习 一 可访问性 基础

教程&#xff1a;Accessibility – Material Design 3 需要科学上网&#xff0c;否则图片显示不出来。设计教程没有图片说明&#xff0c;不容易理解。 优化UI方向 清晰可见的元素足够的对比度和尺寸重要性的明确等级一眼就能辨别的关键信息 传达某一事物的相对重要性 将重…

蓝牙系列七:开源蓝牙协议栈BTStack数据处理(Wireshark抓包分析)

继续蓝牙系列的研究。 在上篇博客&#xff0c;通过阅读BTStack的源码&#xff0c;大体了解了其框架&#xff0c;对于任何一个BTStack的应用程序都有一个main函数&#xff0c;这个main函数是统一的。这个main函数做了某些初始化之后&#xff0c;最终会调用到应用程序提供的btst…

学习Java的第八天

本节我们重点研究对象和类的概念。 对象&#xff08;Object&#xff09;是一个应用系统中的用来描述客观事物的实体&#xff0c;是有特定属性和行为&#xff08;方法&#xff09;的基本运行单位。是类的一个特殊状态下的实例。对象可以是一个实体、一个名词、一个可以想象为有…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:MenuItemGroup)

该组件用来展示菜单MenuItem的分组。 说明&#xff1a; 该组件从API Version 9开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 包含MenuItem子组件。 接口 MenuItemGroup(value?: MenuItemGroupOptions) 参数&#xff1a; 参…

搜索组件的编写与数据的联动

src\components\SearchInput\index.vue 搜索组件编写 <template><div class"search-wrap"><input type"text":placeholder"placeholder":maxlength"maxlength":value"inputValue"input"searchData($ev…

软件测试 - postman高级使用

断言 概念&#xff1a;让程序代替人判断测试用例执行的结果是否符合预期的一个过程 特点&#xff1a; postman断言使用js编写&#xff0c;断言写在postman的tests中 tests脚本在发送请求之后执行&#xff0c;会把断言的结果最终在testresult中进行展示 常用的postman提供的…

Linux系统架构----nginx的访问控制

nginx的访问控制 一、nginx基于授权的访问控制概述 Nginx与Apache一样&#xff0c;可以实现基于用户权限的访问控制&#xff0c;当客户端想要访问相应的网站或者目录时&#xff0c;要求用户输入用户名和密码&#xff0c;才能正常访问配置步骤生成用户密码认证文件 &#xff1…

48. 【Linux教程】yum 软件包管理

本小节介绍如何在 Linux 系统中使用 yum 命令软件管理。 1.yum 简介 yum 是 Red Hat 软件包管理器&#xff0c;它能够查询有关可用软件包的信息&#xff0c;从存储库获取软件包&#xff0c;安装和卸载软件包&#xff0c;以及将整个系统更新到最新的可用版本。yum 在更新&#…

sql注入基础学习

1.常用SQL语句 01、显示数据库 show databases&#xff1b; 02、打开数据库 use db name&#xff1b; 03、显示数据表 show tables&#xff1b; 04、显示表结构 describe table_name&#xff1b; 05、显示表中各字段信息&#xff0c;即表结构 show columns from table_nam…

c++初阶------类和对象(下)

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

河北政采网2024年的入驻要求?

河北政采网2024年的入驻要求主要包括以下几个方面&#xff1a; 经营范围与资质&#xff1a;申请者需具有合法经营的营业执照&#xff0c;可以是一般纳税人、小规模纳税人或个体工商户。同时&#xff0c;申请者需要具备自主电商平台&#xff0c;该平台应为面向社会消费的专业销…

Linux学习(3)——使用Linux命令行

1.Shell是什么&#xff1f; shell本质上是Linux的应用程序&#xff0c;是Linux和用户进行沟通的桥梁 用户可以通过控制台终端输入各种命令&#xff0c;命令会被shell解析&#xff0c;解析后就会调用命令所对应的应用程序&#xff0c;应用程序又会去调用各种API接口以使用Linux内…

锐捷 EWEB auth 远程命令执行漏洞复现

一、漏洞信息 漏洞名称:锐捷 EWEB auth 远程命令执行漏洞 漏洞类别:远程代码执行 风险等级:高危 二、漏洞描述 锐捷睿易是锐捷网络针对商业市场的子品牌。拥有易网络、交换机、路由器、无线、安全、云服务六大产品线,解决方案涵盖商贸零售、酒店、KTV、网吧、监控安防…

【嵌入式——QT】文件系统和文件读写

【嵌入式——QT】文件系统和文件读写 文本文件读写二进制文件读写文件目录操作QCoreApplicationQFileQFileInfoQDirQTemporaryDir和QTemporaryFileQFileSystemWatcher 图示代码示例 文本文件读写 QT提供了两种读写纯文本文件的基本方法&#xff0c;一种是用QFile类的IODevice读…

java SSM科研管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM科研管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S…

VS Code搭建windows+远程Linux上Docker的开发环境

在本地windows桌面系统远程Linux上Docker搭建开发环境主要步骤如下&#xff1a; 一、安装vs code和插件 在windows系统上安装vs code&#xff0c;并安装好remote-ssh、dev-container插件&#xff0c;也可以直接安装Remote Development&#xff0c;他会默认把vs code远程的几种…

网络请求与数据解析

urllib是Python自带的标准库中用于网络请求的库 &#xff0c;无需安装&#xff0c;直接引用即可。通常用于爬虫开发、API&#xff08;应用程序编程接口&#xff09;数据获取和测试。 urllib库的几个模块&#xff1a; urllib.request :用于打开和读取URLurllib.error:包含提出…

大模型相关算法模型学习

对Transformer中Add&Norm层的理解-CSDN博客 GPT模型总结【模型结构及计算过程_详细说明】_gpt结构-CSDN博客 推荐30个以上比较好的中文nlp意图识别模型源码&#xff1f;-CSDN博客 Few-shot learning&#xff08;少样本学习&#xff09;入门 - 知乎 (zhihu.com) 零次学习…

程序人生 - 爬虫者,教育也!

作为一个站长&#xff0c;你是不是对爬虫不胜其烦&#xff1f;爬虫天天来爬&#xff0c;速度又快&#xff0c;频率又高&#xff0c;服务器的大量资源被白白浪费。 看这篇文章的你有福了&#xff0c;我们今天一起来报复一下爬虫&#xff0c;直接把爬虫的服务器给干死机。 本文有…
最新文章