当前位置: 首页 > article >正文

能省一点是一点 - 享元模式(Flyweight Pattern)

享元模式(Flyweight Pattern)

  • 享元模式(Flyweight Pattern)
    • 享元模式(Flyweight Pattern)概述
      • 享元模式包含的角色:
      • 享元模式应用场景
    • talk is cheap, show you my code
    • 总结

享元模式(Flyweight Pattern)

享元模式(Flyweight Pattern)是一种结构型设计模式,它主要用于减少创建大量细粒度对象所带来的内存占用问题。通过共享尽可能多的对象,即所谓的“享元”,来减少内存使用量和提高性能。这种设计模式特别适合于需要大量创建相同对象的情况。而且不要被享元这个名称迷惑,Flyweight的意思是轻量级的意思,更多的意思,这个模式是想告诉共享内存对象这个意思。

为什么会有这种设计模式
比如,当我们要构建的系统中有大量基本一样的元素的时候。
在这里插入图片描述
小时候我们玩过的像素风的游戏,大家可以看到实际上里面的各种场景就是有大量的基础元素拼装出来的。有很多完全一样的像素块,那对这些像素块,我们不需要每次用的时候都创建新的像素块对象。因为新建新的对象,需要消耗堆内存,而且这种消耗是没有意义的。

享元模式(Flyweight Pattern)概述

当一个软件需要创建大量的对象的时候,就会导致内存消耗过多,系统性能下降。而享元模式就是为了解决这个问题而出现的设计模式。

享元模式(Flyweight Pattern)的核心思想: 如果一个对象实例创建之后不可变的话,反复创建这种实例就变得没有必要,直接向客户端返回一个共享的实例就可以了,这样既节省了内存,还避免了创建对象的过程,提升运行效率。

享元模式包含的角色:

享元模式主要包含以下四种角色

  • 抽象享元(Flyweight)角色:是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
  • 具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。
  • 非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
  • 享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检查系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
    在这里插入图片描述

享元模式应用场景

应用场景其实是围绕着享元模式的核心设计思想,减少对象的创建展开的。大致有下面几种:

  1. 软件设计中有大量相似的对象
  2. 缓存场景
  3. 需要多次重复使用某一个对象的时候

talk is cheap, show you my code

在这里插入图片描述
我们设计围棋的时候,会发现,白棋和黑棋会有很多,但是它们都是一样的。所以我们通过利用享元模式来设计创建围棋中的棋子。

围棋棋子 Go chess pieces

public class GoChessPiecesFactory {
    public static Map<String, AbstractGoChessPieces> map = new HashMap<>();

    public static AbstractGoChessPieces getAbstractGoChessPieces(String color) {
        if (map.containsKey(color)) {
            return map.get(color);
        }else {
            if (color.equals("black")) {
                AbstractGoChessPieces black = new BlackGoChessPieces();
                map.put("black", black);
            }
            if (color.equals("white")) {
                AbstractGoChessPieces white = new WhiteGoChessPieces();
                map.put("white", white);
            }
        }
        return map.getOrDefault(color, null);
    }
}

abstract class  AbstractGoChessPieces {
    String color;

    public abstract void display();

}

class BlackGoChessPieces extends AbstractGoChessPieces {

    @Override
    public void display() {
        System.out.println("black");
    }
}

class WhiteGoChessPieces extends AbstractGoChessPieces {

    @Override
    public void display() {
        System.out.println("white");
    }
}

public class Test4 {
    public static void main(String[] args) {
        AbstractGoChessPieces black = GoChessPiecesFactory.getAbstractGoChessPieces("black");
        AbstractGoChessPieces black1 = GoChessPiecesFactory.getAbstractGoChessPieces("black");
        AbstractGoChessPieces black2 = GoChessPiecesFactory.getAbstractGoChessPieces("black");
        AbstractGoChessPieces white = GoChessPiecesFactory.getAbstractGoChessPieces("white");
        AbstractGoChessPieces white1 = GoChessPiecesFactory.getAbstractGoChessPieces("white");
        System.out.println(black == black1);
        System.out.println(black1 == black2);
        System.out.println(white == white1);

        black.display();
        white.display();
    }

}

输出结果

true
true
true
black
white

代码解释:

  1. AbstractGoChessPieces 抽象类 : 定义了一个抽象类 AbstractGoChessPieces,表示围棋棋子的基本属性和行为。
  2. BlackGoChessPieces 类 :继承自 AbstractGoChessPieces,表示黑色棋子。
  3. WhiteGoChessPieces 类 : 继承自 AbstractGoChessPieces,表示白色棋子。
  4. GoChessPiecesFactory 类 :工厂类 GoChessPiecesFactory 负责创建并缓存 AbstractGoChessPieces 的实例。

总结

当代码实现中出现大量相同对象的时候,我们就可以考虑使用享元模式。这种设计模式通过共享对象,节约了内存空间,提升了系统性能。
优点:

  1. 减少内存中的对象数量
  2. 享元模式外部状态不影响内部状态
    缺点:
  3. 享元模式需要隔离出内外两种状态,会使得代码逻辑变得复杂一点

http://www.kler.cn/a/453509.html

相关文章:

  • LabVIEW生物医学信号虚拟实验平台
  • 在 Vue3 项目中实现计时器组件的使用(Vite+Vue3+Node+npm+Element-plus,附测试代码)
  • 机器学习之KNN算法预测数据和数据可视化
  • 24 go语言(golang) - gorm框架安装及使用案例详解
  • 2. SQL窗口函数使用
  • Echarts连接数据库,实时绘制图表详解
  • 大语言模型(LLM)中大数据的压缩存储及其重要性
  • Redis单线程快的原因
  • 21天掌握javaweb-->第19天:Spring Boot后端优化与部署
  • MyBatis的插件运行原理,与如何编写一个插件
  • 人、机、环境中各有其神经网络系统
  • 敏捷开发在前端团队的应用
  • Vue单页应用的配置
  • datahub 汉化
  • Go的select的运行原理
  • elasticsearch upsert 使用
  • Java全栈项目 - 汽车维修服务管理平台
  • windows相关
  • 音视频入门知识(一):基本概念篇
  • Golang 为什么没有注解?
  • [青少年CTF练习平台]Lihua‘s for
  • Unity 战斗系统中角色UI血条设计
  • 微服务分布式(一、项目初始化)
  • JVM实战—2.JVM内存设置与对象分配流转
  • git clone 和 conda 换源
  • 智慧城管综合执法系统源码,移动端+PC端的“两端”应用模式