设计模式结构型——享元模式

news2024/11/27 13:32:38

目录

什么是享元模式

享元模式的实现

享元模式的特点


什么是享元模式

        享元模式(Flyweight Pattern)是一种结构型设计模式,享元模式中的“享元”指被共享的单元,享元模式通过复用对象,以达到节省内存的目的。要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式。其主要解决的问题是创建大量相似对象时的内存开销过大。

        其意图运用共享技术有效地支持大量细粒度的对象。解决在有大量对象时,有可能会造成内存溢出问题,把其中共同的部分抽象出来,查找时直接返回在内存中已有的对象,没有才重新创建,避免重新创建已有对象。减少创建对象的数量,以减少内存占用和提高性能,避免大量相似对象的开销,从而提高系统资源的利用率,尽可能复用现有的同类对象。

        “享元”,被共享的单元,即复用对象,节省内存,注意前提是享元对象是不可变对象。

        当一个系统中存在大量重复不可变对象,就能利用享元模式将对象设计成享元,在内存中只保留一份实例,供引用。这就减少内存中对象的数量,最终节省内存。当然,不仅相同对象可设计成享元,相似对象,也能提取对象中的相同部分(字段)设计成享元。

        “不可变对象”:一旦通过构造器初始化完成后,其状态(对象的成员变量或属性)就不会再被修改。所以,不可变对象不能暴露任何set()等修改内部状态的方法。之所以要求享元是不可变对象,是因为它会被多处代码共享使用,避免一处代码对享元进行了修改,影响到其他使用它的代码。

享元模式的实现

享元(Flyweight )模式中存在以下两种状态:

1. 内部状态,即不会随着环境的改变而改变的可共享部分。

2. 外部状态,指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化。

享元模式的主要有以下角色:

抽象享元角色(Flyweight):通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公 共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法来设置外部数据(外部状态)。

具体享元角色(Concrete Flyweight):实现了抽象享元类,称为享元对象;在具体享元 类中为内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。

非享元角色(Unsharable Flyweight) :并非所有的抽象享元类的子类都需要被共享,不 能被共享的子类可设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过实例化创建。

享元工厂角色(Flyweight Factory):负责创建和管理享元角色。当客户对象请求一个享元 对象时,享元工厂检査系统中是否存在符合要求的享元对象,存在则提供给客户,不存在新创建提供给客户。
享元模式类图:

享元模式代码实现:

抽象享元角色

package com.common.demo.pattern.flyweight;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 抽象享元角色 篮球
 * @date 2023/07/21 15:03:57
 */
public interface BasketBall {

    void play();
}

具体享元角色和非享元角色

package com.common.demo.pattern.flyweight;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 具体享元角色 体育馆
 * @date 2023/07/21 15:05:37
 */
public class Gymnasium implements BasketBall{

    private String gymnasiumName;

    private String sport = "篮球";

    double price = 50;

    public Gymnasium() {
    }

    public Gymnasium(String gymnasiumName) {
        this.gymnasiumName = gymnasiumName;
    }

    public String getGymnasiumName() {
        return gymnasiumName;
    }

    public void setGymnasiumName(String gymnasiumName) {
        this.gymnasiumName = gymnasiumName;
    }

    public String getSport() {
        return sport;
    }

    public void setSport(String sport) {
        this.sport = sport;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public void play() {
        System.out.println("Gymnasium{" + "gymnasiumName='" + gymnasiumName + '\'' +
                ", sport='" + sport + '\'' + ", price=" + price + '}'
                +", this Object='" + this + '\'' );
    }

}

享元工厂角色

package com.common.demo.pattern.flyweight;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 享元工厂 篮球工厂
 * @date 2023/07/21 15:11:37
 */
public class BasketBallFactory {

    private static Map<String,Gymnasium> MAP = new HashMap<>();

    public static Gymnasium getBasketBall(String gymnasiumName){
        Gymnasium gymnasium = MAP.get(gymnasiumName);
        if(Objects.isNull(gymnasium)){
            gymnasium = new Gymnasium(gymnasiumName);
            MAP.put(gymnasiumName,gymnasium);
        }
        return gymnasium;
    }
}

测试类

package com.common.demo.pattern.flyweight;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc
 * @date 2023/07/21 15:16:00
 */
public class Test {

    private static final List<String> nameList = new ArrayList<>();

    public static void main(String[] args) {
        nameList.add("斯塔普斯中心球馆");
        nameList.add("大通中心球馆");
        nameList.add("麦迪逊花园球馆");
        nameList.add("联合中心球馆");
        nameList.add("速贷中心球馆");
        nameList.add("斯塔普斯中心球馆");
        nameList.add("速贷中心球馆");
        nameList.add("美航球馆");
        nameList.add("丹佛百事中心球馆");

        for (String name : nameList){
            BasketBallFactory.getBasketBall(name).play();
        }
    }
}

测试截图

享元模式的特点

优点:

  1. 大大减少对象的创建,对象复用,降低系统的内存,使效率提高。

缺点:

  1. 提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成线程安全问题。
  2. 需要牺牲一定的时间和空间,来实现对象共享和控制机制。当对象之间没有复用性时,使用享元模式可能会导致额外的开销。

使用场景:

  1. 系统有大量相似对象。
  2. 当对象需要被共享时,如需要缓冲池的场景。
  3. 当系统的内存资源相对有限时可以考虑使用享元模式,以减少内存的使用。
  4. 当需要减少对象的创建次数、降低系统开销时。

注意事项:

  1. 注意划分外部状态和内部状态,否则可能会引起线程安全问题。
  2. 这些类必须有一个工厂对象加以控制。

更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)

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

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

相关文章

[数学建模] [2019年A 模拟练习][层次分析法、熵值法、多目标优化、主成分分析法] 4. 深圳居民健康水平评估与测控模型研究

1、前言 2019年“深圳杯”数学建模挑战赛A题 原题&#xff0c;这个是当时学校内部校赛所作&#xff0c;为了拿到参加国赛名额&#xff0c;也权当是做一个简单的练手。 本次练习属于综合评判类&#xff0c;常用的方法无非 层次分析法、熵值法、多目标优化、主成分分析法 等&am…

简单了解内存泄漏(C++)

文章目录 定义举例内存泄漏的危害内存泄漏的种类如何避免内存泄漏 定义 内存泄漏是指在程序运行过程中&#xff0c;申请的内存空间没有被正确释放或回收&#xff0c;导致这些内存无法再次使用的情况。简而言之&#xff0c;内存泄漏就是程序中已经分配的内存没有被及时释放&…

APP抓包-代理转发绕过反代理+Xposed绕过证书校验

某牛牛安卓app防抓包 夜神模拟器打开牛牛&#xff0c;出现网络连接失败等情况。明明网络一切正常&#xff0c;为什么会这样呢&#xff1f; 因为牛牛设置了反代理&#xff0c;而我开启了代理 burp也无任何牛牛的数据包产生 关闭代理之后牛牛就正常了&#xff0c;可恶的牛牛啊&am…

Localizing Moments in Video with Natural Language论文笔记

0.文献地址 2017 Localizing Moments in Video with Natural Language 1.摘要 提出了Moment Context Network&#xff08;MCN&#xff09;有效地定位视频中的自然语言查询又提出了唯一识别对应时刻的文本描述的数据集DiDeMo 2.引言 作者提出了问题如果查询特定的时间段&am…

算法竞赛备赛之经典数据结构训练提升,暑期集训营培训

1.链表与邻接表&#xff1a;树与图的存储 我们将结构体和指针结合来实现链表 struct Node {int val;Node * next; }; ​ new Node;//这样创建结点是相当慢的 我们算法主要是用数组来模拟链表&#xff0c;这样效率会高一些。 数组模拟单链表 邻接表&#xff1a;存储图和树 实…

Spring Cloud【实现用户鉴权(什么是JWT、JWT原理、用户微服务、JWT工具类、用户服务实现JWT鉴权)】(八)

目录 Gateway解决如何允许跨域 服务网关Gateway实现用户鉴权_什么是JWT 服务网关Gateway实现用户鉴权_JWT原理 服务网关Gateway实现用户鉴权_用户微服务 服务网关Gateway实现用户鉴权_JWT工具类 服务网关Gateway实现用户鉴权_用户服务实现JWT鉴权 Gateway解决如何允许跨域…

5分钟开发一个AI论文抓取和ChatGPT提炼应用

5分钟开发一个AI论文抓取和ChatGPT提炼应用 第一步 点击“即刻开始” -选择模板 python -修改标题 “AIPaper”&#xff0c;项目标识“AIPaper”&#xff0c;点击“创建项目” 第二步 在编程区域右侧AI区域&#xff0c;输入框输入以下内容&#xff1a; 请根据下面的内容&…

4.3 Bootstrap CSS编码规范

文章目录 Bootstrap CSS编码规范语法声明顺序不要使用 import媒体查询&#xff08;Media query&#xff09;的位置带前缀的属性单行规则声明简写形式的属性声明Less 和 Sass 中的嵌套注释class 命名选择器代码组织编辑器配置 Bootstrap CSS编码规范 语法 用两个空格来代替制表…

Autosar通信入门系列04-聊聊CAN通信的Basic-CAN与Full-CAN

本文框架 1. 概述2. 基本内容2.1 什么是Basic-CAN与Full-CAN&#xff1f;2.2 既生瑜何生亮&#xff1f; 3. 不同报文类型如何选择Basic-CAN与Full-CAN&#xff1f; 1. 概述 在CAN通信学习时我们经常会遇到或者听同事聊到Basic-CAN与Full-CAN&#xff0c;单从字面上很难理解两个…

计讯物联工业路由器基于5G LAN技术成为工业互联网发展的“加速器”

随着5G的成熟发展&#xff0c;其易部署、低时延、高可靠、大带宽、广连接的特性助力传统工业智能数字化转型&#xff0c;解决了传统工业的布线繁琐、通信环境复杂易造成干扰、对时延与稳定性更加敏感、移动通信的网络需求、海量设备互联等难题。然而&#xff0c;5G在工业制造领…

软件测试基础 - 自动化测试技术

目录 前言&#xff1a; 什么是自动化测试&#xff1f; 自动化测试的优势&#xff1a; 自动化测试的劣势&#xff1a; 适合实施测试自动化的项目&#xff1a; 推行自动化测试的阻力&#xff1a; 软件研发生命周期各个阶段的自动化测试技术 前言&#xff1a; 软件测试是一…

还在手动维护Yapi?

因前后端人员通过接口定义字段&#xff0c;返回值等对接时非常苦恼&#xff0c;没有一个很好的平台维护&#xff0c;后端每次迭代都要写开发文档&#xff0c;需求变化&#xff0c;多系统联调等&#xff0c;给前后端联调造成阻塞。 1、后端开发文档编写规范 1&#xff09;文档…

DataWhale AI夏令营——机器学习

DataWhale AI夏令营——机器学习 学习记录一1. 异常值分析2. 单变量箱线图可视化3. 特征重要性分析 学习记录一 锂电池电池生产参数调控及生产温度预测挑战赛 已配置环境&#xff0c;跑通baseline&#xff0c;并在此基础上对数据进行了简单的分析。 1. 异常值分析 对训练集…

Python知识使用目录体系

Python知识使用目录体系 前记&#xff1a;开始以Get No.方式进行记录&#xff0c;知识体系的建立 Get No. No1: IDEA&#xff08;Java主要编辑器&#xff09;中添加Python插件;(就在此总目录中写&#xff0c;属于纪念开始) 附加&#xff1a;另外一个pycharm工具使用python工…

pyqt5中的控件

字体部分 学习如何加载本地字体a.tff import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton from PyQt5.QtGui import QFont, QFontDatabaseclass MyWindow(QWidget):def __init__(self):super().__init__()self.button Noneself.label None…

【Java开发】 Mybatis-Plus 06:通用枚举功能

枚举类是开发时绕不开的话题&#xff0c; Mybatis-Plus 也提供了简便的枚举功能&#xff0c;快学起来吧~ 目录 1 版本区别 2 通用枚举功能实现 2.1 创建枚举类 2.2 实体类新增枚举字段 3 枚举字段测试 3.1 新增 ① 后台指定枚举 ② 前后端交互 3.2 查询 3.3 修改 ①…

递归排序算法快速排序的实现过程

快速排序(Insertion Sort)也是一种递归排序算法。 快速排序原理&#xff1a;先以列表中的任意一个数为基准(一般选头或尾)&#xff0c;将列表分为左、右两个子列表。 左子列表的数要比基准数小&#xff0c;右子列表的数要比基准数大。然后继续把左子列表和右子列表按同样的方…

蓝桥杯专题-真题版含答案-【九宫幻方】【打鱼还是晒网】【阶乘尾数零的个数】【等差素数列】

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

【Java】重写compareTo()方法给对象数组排序

我们先给一个数组排序&#xff0c;我们肯定用的是Arrays.sort()方法&#xff1a; public class test2 {public static void main(String[] args) {int[] arr{3,5,4,6,9,8,1};System.out.println(Arrays.toString(arr));System.out.println("---------");Arrays.sort…

【一文详解 requests 库中 json 参数和 data 参数的用法】

在requests库当中&#xff0c;requests请求方法&#xff0c;当发送post/put/delete等带有请求体 的请求时&#xff0c;有json和data2个参数可选。 众所周知&#xff0c;http请求的请求体格式主要有以下4种&#xff1a;application/jsonapplicaiton/x-www-from-urlencoded multi…