享元模式(结构型)

news2024/11/18 15:46:42

目录

一、前言

二、享元模式

三、总结


一、前言

        享元模式(Flyweight Pattern)是一种结构型设计模式,用于减少大量细粒度对象的内存占用。它通过共享尽可能多的相同数据来节约内存空间。

        享元模式由以下角色组成:

Flyweight(享元):

一个接口或抽象类,定义了对象的外部状态和内部状态的方法

ConcreteFlyweight(具体享元):

实现享元接口的具体类,包含享元对象的内部状态

UnsharedConcreteFlyweight(非享元):

不需要共享的对象

FlyweightFactory(享元工厂):

创建和管理享元对象,确保共享的享元对象被正确地使用

        整个享元模式的结构图:

二、享元模式

        我们可以以围棋为例,围棋坐标是19*19=361,围棋只有两种颜色,黑色和白色,有很多棋子,此时我们可以利用享元模式,所有黑棋共享一个对象,所有白棋共享一个对象,棋子格子的位置不同,因此位置可以设置为不共享的对象。

        首先创建围棋享元接口类GoPiece.class:

/**
 * @Author dengyifan
 * @create 2024/7/24 14:26
 * @description 享元接口
 */
public interface GoPiece {
    String getColor();

    void place(int x, int y);
}

        再创建黑棋对象BlackPiece.class:

/**
 * @Author dengyifan
 * @create 2024/7/24 14:26
 * @description 具体享元类,黑棋
 */
public class BlackPiece implements GoPiece{
    private final String color = "Black";

    @Override
    public String getColor() {
        return color;
    }

    @Override
    public void place(int x, int y) {
        System.out.println("棋子:" + color + ",位置信息:(" + x + ", " + y + ")");
    }
}

        白棋对象WhitePiece.class:

/**
 * @Author dengyifan
 * @create 2024/7/24 14:26
 * @description 具体享元类,白棋
 */
public class WhitePiece implements GoPiece{
    private final String color = "White";

    @Override
    public String getColor() {
        return color;
    }


    @Override
    public void place(int x, int y) {
        System.out.println("棋子:" + color + ",位置信息:(" + x + ", " + y + ")");
    }
}

        编写享元工厂GoPieceFactory.class:

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

/**
 * @Author dengyifan
 * @create 2024/7/24 14:26
 * @description 享元工厂
 */
public class GoPieceFactory {
    private static final Map<String, GoPiece> pieceMap = new HashMap<>();

    public static GoPiece getPiece(String color) {
        GoPiece piece = pieceMap.get(color);
        if (piece == null) {
            if (color.equalsIgnoreCase("Black")) {
                piece = new BlackPiece();
            } else if (color.equalsIgnoreCase("White")) {
                piece = new WhitePiece();
            }
            pieceMap.put(color, piece);
        }
        return piece;
    }
}

        棋盘类BoardPosition.class:

/**
 * @Author dengyifan
 * @create 2024/7/24 14:29
 * @description 棋盘位置类,包含享元对象和位置,共享GoPiece对象,以及不共享的x、y位置信息
 */
public class BoardPosition {
    private final int size;
    private final GoPiece[][] board;

    public BoardPosition(int size) {
        this.size = size;
        this.board = new GoPiece[size][size];
    }

    public void placePiece(String color, int x, int y) {
        GoPiece piece = GoPieceFactory.getPiece(color);
        board[x][y] = piece;
        piece.place(x, y);
    }

    public void printBoard() {
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (board[i][j] != null) {
                    System.out.print(board[i][j].getColor().charAt(0) + " ");
                } else {
                    System.out.print(". ");
                }
            }
            System.out.println();
        }
    }

    public GoPiece getPieceAt(int x, int y) {
        return board[x][y];
    }
}

         客户端调用类:

/**
 * @Author dengyifan
 * @create 2024/7/24 14:27
 * @description
 */
public class Client {
    public static void main(String[] args) {
        BoardPosition board = new BoardPosition(19);

        board.placePiece("Black", 1, 2);
        board.placePiece("White", 2, 3);
        board.placePiece("Black", 3, 4);
        board.placePiece("White", 4, 5);

        board.printBoard();

        GoPiece piece1 = board.getPieceAt(1, 2);
        GoPiece piece2 = board.getPieceAt(2, 3);
        GoPiece piece3 = board.getPieceAt(3, 4);
        GoPiece piece4 = board.getPieceAt(4, 5);

        System.out.println("棋子1和棋子3: " + (piece1 == piece3));
        System.out.println("棋子2和棋子4: " + (piece2 == piece4));
    }
}

        运行结果:

三、总结

        优点与缺点

优点:

减少对象数量:

通过共享技术可以有效减少内存中的对象数量,从而提高系统的性能

节约内存:

共享的享元对象能够极大地节约内存空间

缺点:

复杂性增加:

系统中引入了享元工厂和共享机制,增加了系统的复杂性

非共享对象:

并不是所有的对象都适合使用享元模式,对于那些包含大量不变数据的对象,享元模式才有明显的优势

        应用场景:

文本编辑器:

在文本编辑器中,每个字符可以看作是一个对象。如果文档非常大,这些字符对象将占用大量内存。使用享元模式,可以将相同字符的对象共享起来,显著减少内存消耗

图形系统:

在图形系统中,经常需要绘制大量相同或相似的图形元素,如点、线、圆等。通过享元模式,可以将相同的图形对象共享,以节约内存

数据库连接池:

在数据库应用中,创建和销毁数据库连接的开销很大。使用享元模式,可以创建一个数据库连接池,所有的数据库连接都从池中获取和释放,从而提高性能和资源利用率

游戏开发:

在游戏开发中,大量的游戏对象(如树木、建筑物、NPC等)需要频繁使用。使用享元模式,可以将相同类型的游戏对象共享,从而减少内存占用,提高游戏性能

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

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

相关文章

【OpenCV C++20 学习笔记】扫描图片数据

扫描图片数据 应用情景图像数据扫描的难点颜色空间缩减&#xff08;color space reduction&#xff09;查询表 扫描算法计算查询表统计运算时长连续内存3种扫描方法C风格的扫描方法迭代器方法坐标方法LUT方法 算法效率对比结论 应用情景 图像数据扫描的难点 在上一篇文章《基…

项目一缓存商品

文章目录 概要整体架构流程技术细节小结 概要 因为商品是经常被浏览的,所以数据库的访问量就问大大增加,造成负载过大影响性能,所以我们需要把商品缓存到redis当中,因为redis是存在内存中的,所以效率会比MySQL的快. 整体架构流程 技术细节 我们在缓存时需要保持数据的一致性所…

AHK是让任何软件都支持 Shift + 鼠标滚轮 实现界面水平滚动

目录 基本介绍 详细特点 图解安装 下载失败&#xff1f;缓慢&#xff1f; 创建并运行脚本代码&#x1f603; 新建空 xxx.ahk文件 vscode/记事本等编辑工具打开 复制并粘贴简易脚本 运行 其他问题 问题一&#xff1a;弹出无法执行此脚本 关闭脚本 基本介绍 AutoHot…

zookeeper开启SASL权限认证

目录 一、SASL介绍 二、使用 SASL 进行身份验证 2.1 服务器到服务器的身份验证 2.2 客户端到服务器身份验证 三、验证功能 一、SASL介绍 默认情况下&#xff0c;ZooKeeper 不使用任何形式的身份验证并允许匿名连接。但是&#xff0c;它支持 Java 身份验证与授权服务(JAAS)…

用户需要什么-软件的工程可用性(第一部分)01

Larry L. Constantine 著&#xff0c;Huang Yin 译 “究竟用户的需要是什么&#xff1f;”如果 Fred 作为一个程序员而不是一个心理学家时他可能会提出这 样一个问题。用户们通常需要更多&#xff0c;而开发人员似乎看上去并不能很好的领会并更好的满足他们。对于我们而言&…

WPF使用TouchSocket实现Tcp client

文章目录 前言1、页面展示2、主页面UI代码2、TCP client的UI代码3、Tcp client后台代码实现4、UI与后台代码的关联 前言 在该篇的Demo中&#xff0c;您可以找到以下内容&#xff1a; 1、TouchSocket的使用&#xff1b; 2、CommunityToolkit.Mvvm的使用&#xff1b; 3、AvalonD…

IF=8.5 MIMIC-IV高阶玩法!中国用新指标SHR+机器学习拿一区top,思路太牛了

‍ MIMIC-IV 发文难&#xff1f;那是你还没遇到对的思路&#xff01;如今机器学习数据库挖掘的文章层出不穷&#xff0c;今天介绍的这篇文章是在MIMIC-IV数据库的基础上&#xff0c;用了一个新指标—应激性高血糖比&#xff08;SHR&#xff09;&#xff0c;结合机器学习构建预测…

【iOS】——Block循环引用

循环引用原因 如果在Block中使用附有_ _strong修饰符的对象类型自动变量&#xff0c;那么当Block从栈复制到堆时&#xff0c;该对象为Block所持有&#xff0c;这样容易引起循环引用。 HPPerson *person [[HPPerson alloc] init];person.block ^{NSLog("person.age--- …

Redis使用场景-热点数据缓存

什么是缓存&#xff1f; 为了把一些经常访问的数据放入缓存中已减少对数据库的访问&#xff0c;从而减少数据库的压力&#xff0c;提高程序的性能。【内存中存储】-效率快 缓存的原理 什么样的数据适合放入缓存中&#xff1f; 1.查询频率高且修改频率低 2.数据安全性低 哪些组件…

《python语言程序设计》第6章第7题财务应用程序:计算未来投资,编写函数计算制定年数以给定利率

记住这里增加循环应该是以年为单位。但是添加的数是月为单位 此处需留意其实点不是1&#xff0c;1代表1年&#xff0c;这里月所以其实是12&#xff0c;这里的单位是月&#xff0c;而不是年。 python for i in range(12,monthNum12,12) 如果你把12都换成1呢&#xff1f;&…

本地生活抽佣系统搭建:如何让系统具有竞争优势?

随着本地生活的潜力不断展现&#xff0c;本地生活服务商逐渐成为新兴职业中的一大热门&#xff0c;本地生活抽佣系统搭建的热度也一直保持着飙升的状态。 抖音生活发布的《2023年数据报告》显示&#xff0c;2023年&#xff0c;抖音生活服务平台总交易额增长256%&#xff0c;抖…

监测Nginx访问日志状态码,并做相应动作

文章目录 引言I 监测 Nginx 访问日志情况,并做相应动作1.1 前提准备1.2 访问日志 502 情况,重启 bttomcat9服务1.3 其他案例:访问日志 502 情况,重启 php-fpm 服务II 将Shell 脚本check499.sh包装成systemd服务2.1 创建systemd服务2.2 配置service2.3 开机启动2.4 其他常用…

自监督学习概述(Self-Supervised Learning,SSL)

自监督学习&#xff08;Self-Supervised Learning&#xff0c;SSL&#xff09;是一种机器学习方法&#xff0c;旨在利用未标记数据进行训练。这种方法通过从数据本身生成伪标签&#xff0c;来创建监督信号&#xff0c;使得模型能够学习有效的数据表示。自监督学习在深度学习领域…

HTTP传输下载和P2P传输下载的区别?

HTTP传输下载和P2P&#xff08;Peer-to-Peer&#xff09;传输下载在多个方面存在显著的区别&#xff0c;以下是详细的分析&#xff1a; 1. 工作原理 HTTP传输下载&#xff1a; HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是一种用于在Web上进行数据通信的协议&…

PHP多功能投票系统源码小程序

&#x1f389;决策不再难&#xff01;「多功能投票小程序」一键搞定所有选择困难症✨ &#x1f914;选择困难&#xff1f;「多功能投票小程序」来救场&#xff01; 每次聚会、团队讨论还是日常小决策&#xff0c;是不是总有那么几个瞬间让你陷入“选哪个好呢&#xff1f;”的…

spine to unity-2.利用边缘框实现实时碰撞检测

主要讲spine的边缘框&#xff0c;在unity中&#xff0c;实现实时碰撞检测。其中使用的素材&#xff0c;是我为独立游戏ink制作的动画。独立游戏ink的开发日志&#xff0c;在小红薯持续更新中。spine工具包的安装&#xff0c;下载请参考spine to unity-1spine BoundingBoxFollow…

【MySQL篇】Percona XtraBackup标准化全库完整备份策略(第三篇,总共五篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

STM32H7的LPUART基础和唤醒示例

STM32H7的LPUART基础知识 硬件框图低功耗的高级特性低功耗串口的时钟以及波特率低功耗串口发送时序低功耗串口支持的唤醒方式 LPUART 的全称是 Low power universal synchronous asynchronous receiver transmitter&#xff0c;中文意思是低功耗通用异步收发器&#xff0c;简称…

【C语言】栈的实现(数据结构)

前言&#xff1a; 还是举一个生活中的例子&#xff0c;大家都玩过积木&#xff0c;当我们把积木叠起来的时候&#xff0c;如果要拿到最底部的积木&#xff0c;我们必须从顶端一个一个打出&#xff0c;最后才能拿到底部的积木&#xff0c;也就是后进先出&#xff08;先进后出&a…

Python - 开源库 ReportLab 库合并 CVS 和图像生成 PDF 文档

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/140281680 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Report…