【深入理解设计模式】享元设计模式

news2024/12/25 8:56:10

享元设计模式

在这里插入图片描述

概述

享元设计模式(Flyweight Design Pattern)是一种用于性能优化的设计模式,它通过共享尽可能多的相似对象来减少对象的创建,从而降低内存使用和提高性能。享元模式的核心思想是将对象的共享部分提取出来,使得多个对象可以共享同一个享元对象,从而减少对象的创建。

定义:

​ 运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似对象的开销,从而提高系统资源的利用率。

结构

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

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

享元模式的结构如下:

  1. 抽象享元类(Flyweight):定义一个抽象类,包含一个享元对象的属性以及一个构造函数。

  2. 具体享元类(ConcreteFlyweight):实现抽象享元类,定义具体的享元对象。

  3. 享元工厂类(FlyweightFactory):负责创建和管理享元对象。享元工厂类会缓存已经创建的享元对象,当需要获取享元对象时,首先从缓存中查找,如果找不到,则创建一个新的享元对象并将其添加到缓存中。

享元模式的实现示例:

以下是一个简单的享元模式实现示例:

// 抽象享元类
public abstract class Flyweight {
    public abstract void operation();
}

// 具体享元类
public class ConcreteFlyweight extends Flyweight {
    private String state;

    public ConcreteFlyweight(String state) {
        this.state = state;
    }

    @Override
    public void operation() {
        System.out.println("ConcreteFlyweight: " + state);
    }
}

// 享元工厂类
public class FlyweightFactory {
    private Map<String, Flyweight> flyweights = new HashMap<>();

    public Flyweight getFlyweight(String state) {
        if (!flyweights.containsKey(state)) {
            flyweights.put(state, new ConcreteFlyweight(state));
        }
        return flyweights.get(state);
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight flyweight1 = factory.getFlyweight("state1");
        Flyweight flyweight2 = factory.getFlyweight("state2");
        Flyweight flyweight3 = factory.getFlyweight("state1");

        flyweight1.operation();
        flyweight2.operation();
        flyweight3.operation();
    }
}

在这个示例中,我们定义了一个抽象享元类Flyweight和一个具体享元类ConcreteFlyweightFlyweightFactory类负责创建和管理享元对象,它使用一个HashMap来缓存已经创建的享元对象。客户端通过FlyweightFactory类来获取享元对象,并使用它们进行操作。

示例二:

/**
 * @author OldGj 2024/02/29
 * @version v1.0
 * @apiNote 享元设计模式 - 抽象享元类
 */
public abstract class AbstractBox {

    public abstract String getSharp();

    public void display(String color) {
        System.out.println("形状:" + this.getSharp() + ",颜色:" + color);
    }
}

/**
 * @author OldGj 2024/02/29
 * @version v1.0
 * @apiNote 具体享元类 - I图形
 */
public class IBox extends AbstractBox {

    @Override
    public String getSharp() {
        return "I";
    }
}


/**
 * @author OldGj 2024/02/29
 * @version v1.0
 * @apiNote 具体享元类 - L图形
 */
public class LBox extends AbstractBox {

    @Override
    public String getSharp() {
        return "L";
    }
}


/**
 * @author OldGj 2024/02/29
 * @version v1.0
 * @apiNote 具体享元类 - O图形
 */
public class OBox extends AbstractBox {

    @Override
    public String getSharp() {
        return "O";
    }
}

/**
 * @author OldGj 2024/02/29
 * @version v1.0
 * @apiNote 图形工厂类 - 享元工厂类 【单例实现】
 */
public class BoxFactory {

    private final Map<String, AbstractBox> map;
    private static final BoxFactory factory = new BoxFactory();

    private BoxFactory() {
        map = new HashMap<>();
        map.put("I", new IBox());
        map.put("O", new OBox());
        map.put("L", new LBox());
    }

    public static BoxFactory getInstance() {
        return factory;
    }

    public AbstractBox createBox(String name) {
        return map.get(name);
    }
}
/**
 * @author OldGj 2024/02/29
 * @version v1.0
 * @apiNote 客户端 - 测试类
 */
public class Client {

    public static void main(String[] args) {
        BoxFactory factory = BoxFactory.getInstance();
        AbstractBox LBox = factory.createBox("L");
        LBox.display("红色"); // 外部状态

        AbstractBox oBox = factory.createBox("O");
        oBox.display("黑色"); // 外部状态

        AbstractBox IBox = factory.createBox("I");
        IBox.display("白色"); // 外部状态

        AbstractBox IBox2 = factory.createBox("I");
        IBox2.display("蓝色"); // 外部状态
        System.out.println("是否共享同一个对象:" + (IBox == IBox2));
    }
}

在这里插入图片描述

优缺点:

享元模式的优点:

  1. 减少对象创建:享元模式通过共享相似对象,减少了对象的创建,从而降低了内存使用和提高了性能。

  2. 提高性能:享元模式通过减少对象创建,提高了性能。

  3. 方便管理:享元模式将对象的共享部分提取出来,使得对象可以轻松地管理和维护。

享元模式的缺点:

  1. 享元对象共享:享元对象共享可能会导致一些问题,例如线程安全问题。享元模式要求享元对象是线程安全的,这可能会导致性能下降。

  2. 享元对象状态:享元对象的状态可能会影响其他使用相同享元对象的客户端。享元模式要求享元对象的状态是独立的,这可能会导致享元对象的状态难以维护。

  3. 享元对象生命周期:享元对象的生命周期可能会比客户端使用的时间长,这可能会导致内存泄漏。享元模式要求享元对象具有较长的生命周期,这可能会导致内存使用增加。

使用场景:

享元模式通常用于以下场景:

  1. 对象数量多且相似:当对象数量多且相似时,享元模式可以显著减少对象的创建,提高性能。

  2. 对象共享属性多:当对象共享属性多时,享元模式可以减少内存使用,提高性能。

  3. 对象创建开销大:当对象创建开销大时,享元模式可以减少对象创建的开销,提高性能。

JDK源码解析

Integer类使用了享元模式。我们先看下面的例子:

public class Demo {
    public static void main(String[] args) {
        Integer i1 = 127;
        Integer i2 = 127;

        System.out.println("i1和i2对象是否是同一个对象?" + (i1 == i2));

        Integer i3 = 128;
        Integer i4 = 128;

        System.out.println("i3和i4对象是否是同一个对象?" + (i3 == i4));
    }
}

运行上面代码,结果如下:

为什么第一个输出语句输出的是true,第二个输出语句输出的是false?通过反编译软件进行反编译,代码如下:

public class Demo {
    public static void main(String[] args) {
        Integer i1 = Integer.valueOf((int)127);
        Integer i2 Integer.valueOf((int)127);
        System.out.println((String)new StringBuilder().append((String)"i1\u548ci2\u5bf9\u8c61\u662f\u5426\u662f\u540c\u4e00\u4e2a\u5bf9\u8c61\uff1f").append((boolean)(i1 == i2)).toString());
        Integer i3 = Integer.valueOf((int)128);
        Integer i4 = Integer.valueOf((int)128);
        System.out.println((String)new StringBuilder().append((String)"i3\u548ci4\u5bf9\u8c61\u662f\u5426\u662f\u540c\u4e00\u4e2a\u5bf9\u8c61\uff1f").append((boolean)(i3 == i4)).toString());
    }
}

上面代码可以看到,直接给Integer类型的变量赋值基本数据类型数据的操作底层使用的是 valueOf() ,所以只需要看该方法即可

public final class Integer extends Number implements Comparable<Integer> {
    
	public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                }
            }
            high = h;
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }
}

可以看到 Integer 默认先创建并缓存 -128 ~ 127 之间数的 Integer 对象,当调用 valueOf 时如果参数在 -128 ~ 127 之间则计算下标并从缓存中返回,否则创建一个新的 Integer 对象。

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

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

相关文章

推房子游戏c++

这段代码是一个推箱子游戏的实现。游戏中有一个地图&#xff0c;地图上有墙壁、人、箱子和目标位置。玩家通过键盘输入WASD或方向键来控制人物的移动&#xff0c;目标是将所有的箱子推到相应的目标位置上。 代码中的dt数组表示地图&#xff0c;每个位置上的字符表示对应的元素…

分享2024年在家轻松兼职赚钱的5个副业

今天在网上看到这么一句话&#xff0c;真的让我深有感触&#xff1a;“职场人一定要有居安思危的意识&#xff0c;创业的人一定要三思而后行”。在这个瞬息万变的时代&#xff0c;连被视为铁饭碗的公务员、教师等体制内工作都不能保证一辈子的稳定。发展副业&#xff0c;似乎成…

Deepl翻译相关介绍

DeepL是一种机器翻译软件&#xff0c;它在2017年首次发布。该软件利用了神经网络和深度学习技术&#xff0c;以提供更准确和自然的翻译结果。DeepL的翻译质量被广泛认为是当前机器翻译技术中最佳的之一。 官网&#xff1a;DeepL翻译&#xff1a;全世界最准确的翻译 DeepL具有许…

伊理威科技:新手开抖店的教程

在数字浪潮中&#xff0c;抖音小店如星火燎原&#xff0c;吸引无数创业者。你是否也心潮澎湃&#xff0c;想要一试身手?别急&#xff0c;让我们一步步揭开开店的神秘面纱。 注册流程。想象一下&#xff0c;你只需在抖音平台上点击“我要开店”&#xff0c;按提示填写相关信息&…

20240308-2-校招前端面试常见问题-网络及浏览器

校招前端面试常见问题【4】——网络及浏览器 1、网络相关 Q&#xff1a;请简述一下 HTTP 协议&#xff0c;以及 HTTP1.0/1.1/2.0/3.0 的区别&#xff1f; HTTP 协议&#xff1a;超文本传输协议&#xff0c;使用 TCP/IP 协议传输数据。是一个应用层的协议。 HTTP1.0&#xff…

二进制模二除法

例&#xff1a;1100100100 对 1011做模二除法 ① 第一位商 除数 1011 是一个四位二进制数&#xff0c;因此先拿出被除数的前四位(从高位开始取) 11001100 就是本次的被除数&#xff0c;取其首位数 1 作为第一位商然后对 1100 和 1011 做异或运算&#xff0c;得出结果 0111 ②…

HNU-算法设计与分析-甘晴void学习感悟

前言 算法设计与分析&#xff0c;仅就课程而言&#xff0c;似乎是数据结构与算法分析的延续 教材使用&#xff1a; 课程 关于课程&#xff0c;橙学长讲的非常清晰&#xff0c;我深以为然。 HNUCS-大三课程概览-CSDN博客文章浏览阅读1.3k次&#xff0c;点赞5次&#xff0c;收…

【视频图像取证篇】Impress模糊图像增强技术之颜色滤波器场景实例教程(蘇小沐)

【视频图像取证篇】Impress模糊图像增强技术之颜色滤波器场景实例教程&#xff08;蘇小沐&#xff09; Impress模糊图像增强技术之颜色滤波器场景实例教程—【蘇小沐】 1、实验环境 系统环境Impress&#xff0c;[v8.2.02]Windows 11 专业版&#xff0c;[23H2&#xff08;226…

B端系统优化,可不是换个颜色和图标,看看与大厂系统的差距。

Hi&#xff0c;我是贝格前端工场&#xff0c;优化升级各类管理系统的界面和体验&#xff0c;是我们核心业务之一&#xff0c;欢迎老铁们评论点赞互动&#xff0c;有需求可以私信我们 一、不要被流于表面的需求描述迷惑。 很多人找我们优化系统界面&#xff0c;对需求总是轻描淡…

win11修改主机mac地址

很多时候&#xff0c;为了限制恶意的蹭流浪&#xff0c;除了分配固定的ip地址外&#xff0c;还限制mac地址。只有mac与ip一致&#xff0c;才能上网冲浪 网络适配器中修改 搜索“控制面板”打开 控制面板 > 网络和Internet > 网络和共享中心 >查看网络状态和任务>…

代码随想录 回溯算法-排序

目录 46.全排序 47.全排列|| 332.重新安排行程 46.全排序 46. 全排列 中等 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,…

【NR技术】 3GPP支持无人机的关键技术以及场景

1 背景 人们对使用蜂窝连接来支持无人机系统(UAS)的兴趣浓厚&#xff0c;3GPP生态系统为UAS的运行提供了极好的好处。无处不在的覆盖范围、高可靠性和QoS、强大的安全性和无缝移动性是支持UAS指挥和控制功能的关键因素。与此同时&#xff0c;监管机构正在调查安全和性能标准以及…

讲讲 SaaS 平台的多租户设计

本篇就来讲讲 SaaS 平台的多租户设计。 以“钉钉”为例看实际的多租户场景 在讲设计之前&#xff0c;我们先以“钉钉”为例&#xff0c;来看看一个 SaaS 平台是如何运作的。相信大部分B 端产品经理都体验过钉钉&#xff0c;我们分两个维度来讲钉钉的租户注册到使用的流程。一…

mysql数据库(下)

目录 约束 约束的概念和分类 1、约束的概念&#xff1a; 2、约束的分类 1、主键约束 2、默认约束 3、非空约束 4、唯一约束 5、外键约束 约束 约束的概念和分类 1、约束的概念&#xff1a; 约束时作用于表中列上的规则&#xff0c;用于限制加入表的数据约束的存在保证…

代码随想录算法训练营第day40|343. 整数拆分 、 96.不同的二叉搜索树

a.343. 整数拆分 题目链接 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。 示例 2: 输入: …

csgo搬砖核心步骤,月入1000-10000你也可以的!

近年网络游戏产业的爆炸式增长&#xff0c;虚拟物品的交易需求也越来越大&#xff0c;为了满足虚拟物品的交易需求&#xff0c;网络游戏交易平台开始兴起和发展。网游交易平台的交易项目包括帐号交易、游戏币交易、装备交易这几种主要交易项目&#xff0c;其交易模式可分为C2C模…

FPGA IBUFG

IBUFG和IBUFGDS的输入端仅仅与芯片的专用全局时钟输入管脚有物理连接&#xff0c;与普通IO和其它内部CLB等没有物理连接。 所以&#xff0c;IBUFG输入的不能直接接另外信号。 GTH transceiver primitives are called GTHE3_COMMON and GTHE3_CHANNEL in UltraScale FPGAs, an…

大数据技术学习笔记(五)—— MapReduce(1)

目录 1 MapReduce 概述1.1 MapReduce 定义1.2 MapReduce 优缺点1.3 MapReduce 核心思想1.4 MapReduce 进程1.5 Hadoop 序列化类型1.6 MapReduce 编程规范1.7 WordCount 案例实操1.7.1 案例需求1.7.2 环境准备1.7.3 编写程序1.7.4 测试 2 MapReduce 序列化2.1 序列化概述2.2 自定…

2023最新群智能优化算法:巨型犰狳优化算法(Giant Armadillo Optimization,GAO)求解23个基准函数(提供MATLAB代码)

一、巨型犰狳优化算法 巨型犰狳优化算法&#xff08;Giant Armadillo Optimization&#xff0c;GAO&#xff09;由Omar Alsayyed等人于2023年提出&#xff0c;该算法模仿了巨型犰狳在野外的自然行为。GAO设计的基本灵感来自巨型犰狳向猎物位置移动和挖掘白蚁丘的狩猎策略。GAO…

2.4_1 死锁的概念

文章目录 2.4_1 死锁的概念&#xff08;一&#xff09;什么是死锁&#xff08;二&#xff09;死锁、饥饿、死循环的区别&#xff08;三&#xff09;死锁产生的必要条件&#xff08;四&#xff09;什么时候会发生死锁&#xff08;五&#xff09;死锁的处理策略 总结 2.4_1 死锁的…