java23种设计模式(十一) -- 享元模式(结构型设计模式)

23种设计模式【Java】全案例解析 具体解析 创建型 结构型 7个原则 单一职责原则【SINGLE RESPONSIBILITY PRINCIPLE】: 一个类负责一项职责。 里氏替换原则【LISKOV SUBSTITUTION PRINCIPLE】: 继承与派生的规则。 依赖倒置原则【DEPENDENCE INVERSION PRINCIPLE】: 高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。即针对接口编程,不要针对实现编程。 接口隔离原则【INTERFACE SEGREGATION PRINC 阅读详情

享元模式

介绍

享元模式,主要在于共享通用对象,减少内存的使用,提升系统的访问效率。而这部分共享对象通常比较耗费内存或者需要查询大量接口或者使用数据库资源,因此统一抽离作为共享对象使用。

另外享元模式可以分为在服务端和客户端,一般互联网H5和Web场景下大部分数据都需要服务端进行处理,比如数据库连接池的使用、多线程线程池的使用,除了这些功能外,还有些需要服务端进行包装后的处理下发给客户端,因为服务端需要做享元处理。但在一些游戏场景下,很多都是客户端需要进行渲染地图效果,比如;树木、花草、鱼虫,通过设置不同元素描述使用享元公用对象,减少内存的占用,让客户端的游戏更加流畅。

在享元模型的实现中需要使用到享元工厂来进行管理这部分独立的对象和共享的对象,避免出现线程安全的问题。

Java中的String类型

在JAVA语言中,String类型就是使用了享元模式。String对象是final类型,对象一旦创建就不可改变。在JAVA中字符串常量都是存在常量池中的,JAVA会确保一个字符串常量在常量池中只有一个拷贝。String a=“abc”,其中"abc"就是一个字符串常量。

		String a = "abc";
        String b = "abc";
        System.out.println(a==b);

上面的例子中结果为:true ,这就说明a和b两个引用都指向了常量池中的同一个字符串常量"abc"。这样的设计避免了在创建N多相同对象时所产生的不必要的大量的资源消耗。

享元模式的结构

享元模式采用一个共享来避免大量拥有相同内容对象的开销。这种开销最常见、最直观的就是内存的损耗。享元对象能做到共享的关键是区分内蕴状态(Internal State)和外蕴状态(External State)。

一个内蕴状态是存储在享元对象内部的,并且是不会随环境的改变而有所不同。因此,一个享元可以具有内蕴状态并可以共享。

一个外蕴状态是随环境的改变而改变的、不可以共享的。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。外蕴状态不可以影响享元对象的内蕴状态,它们是相互独立的。

实例

在这里插入图片描述
通过对围棋软件进行分析,发现在围棋棋盘中包含大量的黑子和白子,它们的形状、大小都一模一样,只是出现的位置不同而已。如果将每一个棋子都作为一个独立的对象存储在内存中,将导致该围棋软件在运行时所需内存空间较大,如何降低运行代价、提高系统性能是需要解决的一个问题。为了解决这个问题,决定使用享元模式来设计该围棋软件的棋子对象

内蕴状态(Internal State)
//围棋棋子类:抽象享元类
public abstract class IgoChessman {
    public abstract String getColor();  
  
    public void display() {  
        System.out.println("棋子颜色:" + this.getColor());    
    }  
}  

//白色棋子类:具体享元类
public class WhiteIgoChessman extends IgoChessman {
    public String getColor() {  
        return "白色";  
    }  
}

//黑色棋子类:具体享元类
public class BlackIgoChessman extends IgoChessman {
    public String getColor() {  
        return "黑色";  
    }     
} 
//围棋棋子工厂类:享元工厂类,使用单例模式进行设计
public class IgoChessmanFactory {
    private static IgoChessmanFactory instance = new IgoChessmanFactory();  
    private static Hashtable ht; //使用Hashtable来存储享元对象,充当享元池
      
    private IgoChessmanFactory() {  
        ht = new Hashtable();  
        IgoChessman black,white;
        black = new BlackIgoChessman();
        ht.put("b",black);  
        white = new WhiteIgoChessman();
        ht.put("w",white);  
    }  
      
    //返回享元工厂类的唯一实例  
    public static IgoChessmanFactory getInstance() {  
        return instance;  
    }  
      
    //通过key来获取存储在Hashtable中的享元对象  
    public static IgoChessman getIgoChessman(String color) {  
        return (IgoChessman)ht.get(color);    
    }  
}  
外蕴状态(External State)

通过对围棋棋子进行进一步分析,发现虽然黑色棋子和白色棋子可以共享,但是它们将显示在棋盘的不同位置,如何让相同的黑子或者白子能够多次重复显示且位于一个棋盘的不同地方?解决方法就是将棋子的位置定义为棋子的一个外部状态,在需要时再进行设置。因此,我们增加了一个新的类Coordinates(坐标类),用于存储每一个棋子的位置

//围棋棋子类:抽象享元类
public abstract class ExternalIgoChessman {
    public abstract String getColor();

    public void display(Coordinates coord){
        System.out.println("棋子颜色:" + this.getColor() + ",棋子位置:" + coord.getX() + "," + coord.getY() );
    }
}  

//白色棋子类:具体享元类
public class ExternalWhiteIgoChessman extends ExternalIgoChessman {
    public String getColor() {  
        return "白色";  
    }  
}

//黑色棋子类:具体享元类
public class ExternalBlackIgoChessman extends ExternalIgoChessman {
    public String getColor() {
        return "黑色";
    }
}  
public class Coordinates {
    private int x;  
    private int y;  
      
    public Coordinates(int x,int y) {  
        this.x = x;  
        this.y = y;  
    }  
      
    public int getX() {  
        return this.x;  
    }  
      
    public void setX(int x) {  
        this.x = x;  
    }  
      
    public int getY() {  
        return this.y;  
    }  
      
    public void setY(int y) {  
        this.y = y;  
    }  
}  
//围棋棋子工厂类:享元工厂类,使用单例模式进行设计
public class ExternalIgoChessmanFactory {
    private static ExternalIgoChessmanFactory instance = new ExternalIgoChessmanFactory();
    private static Hashtable ht; //使用Hashtable来存储享元对象,充当享元池

    private ExternalIgoChessmanFactory() {
        ht = new Hashtable();
        ExternalIgoChessman black, white;
        black = new ExternalBlackIgoChessman();
        ht.put("b", black);
        white = new ExternalWhiteIgoChessman();
        ht.put("w", white);
    }

    //返回享元工厂类的唯一实例  
    public static ExternalIgoChessmanFactory getInstance() {
        return instance;
    }

    //通过key来获取存储在Hashtable中的享元对象  
    public static ExternalIgoChessman getIgoChessman(String color) {
        return (ExternalIgoChessman) ht.get(color);
    }
} 
测试类
@Slf4j
public class ApiTest {

    @Test
    public void testCommand() {
        log.info("--------------------- 内部状态 享元模式 ---------------------");
        IgoChessman black1, black2, black3, white1, white2;
        IgoChessmanFactory factory;

        //获取享元工厂对象
        factory = IgoChessmanFactory.getInstance();

        //通过享元工厂获取三颗黑子
        black1 = factory.getIgoChessman("b");
        black2 = factory.getIgoChessman("b");
        black3 = factory.getIgoChessman("b");
        System.out.println("判断两颗黑子是否相同:" + (black1 == black2));

        //通过享元工厂获取两颗白子
        white1 = factory.getIgoChessman("w");
        white2 = factory.getIgoChessman("w");
        System.out.println("判断两颗白子是否相同:" + (white1 == white2));

        //显示棋子
        black1.display();
        black2.display();
        black3.display();
        white1.display();
        white2.display();

        log.info("--------------------- 外部状态 享元模式 ---------------------");
        ExternalIgoChessman externalBlack1,externalBlack2,externalBlack3,externalWhite1,externalWhite2;
        ExternalIgoChessmanFactory externalFactory;

        //获取享元工厂对象
        externalFactory = ExternalIgoChessmanFactory.getInstance();

        //通过享元工厂获取三颗黑子
        externalBlack1 = externalFactory.getIgoChessman("b");
        externalBlack2 = externalFactory.getIgoChessman("b");
        externalBlack3 = externalFactory.getIgoChessman("b");
        System.out.println("判断两颗黑子是否相同:" + (externalBlack1==externalBlack2));

        //通过享元工厂获取两颗白子
        externalWhite1 = externalFactory.getIgoChessman("w");
        externalWhite2 = externalFactory.getIgoChessman("w");
        System.out.println("判断两颗白子是否相同:" + (externalWhite1==externalWhite2));

        //显示棋子,同时设置棋子的坐标位置
        externalBlack1.display(new Coordinates(1,2));
        externalBlack2.display(new Coordinates(3,4));
        externalBlack3.display(new Coordinates(1,3));
        externalWhite1.display(new Coordinates(2,5));
        externalWhite2.display(new Coordinates(2,4));
    }

}

在这里插入图片描述

小结

享元模式的优点在于它大幅度地降低内存中对象的数量。但是,它做到这一点所付出的代价也是很高的:

  • 享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。
  • 享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。
Java中的23个设计模式 【结构型模式】 中的 【享元模式】 阅读详情

相关推荐

达梦DCA2023年10月培训及考试总结

本次培训共分三天,培训内容不单单是DCA的单机安装、实例创建、库表操作等,培训内容是把关系型数据库的理论及DM8的产品结合起来讲,很实用。具体的考试则是需要个人大量的线下练习,考试总体而言都是培训讲过的内容,只要用心听,好好练习,哪怕是没有计算机基础的童鞋也能考过。提示:以下是本篇文章正文内容,下面案例可供参考总体而言,本次考试不是很难,用心准备,考前认真听讲,考后多次练习,基本都能通过。

qinjuao的博客 2319

Java 享元模式(Flyweight Pattern)详解

Java设计模式之享元模式

小雨点的博客 760

ZYNQ双核通信实战:手把手教你用OpenAMP搭建Linux+FreeRTOS开发环境(2018.3版)

本文详细介绍了如何在ZYNQ平台上使用OpenAMP框架实现双核通信,构建Linux与FreeRTOS协同开发环境。从开发环境配置、系统组件编译到OpenAMP框架应用,手把手指导开发者完成ZYNQ双核通信系统的搭建与调试,为异构计算开发提供实用解决方案。

weixin_33737134的博客 475

JAVA设计模式之享元模式详解

享元模式 (flyweight pattern) 的原始定义是:摒弃了在每个对象中保存所有数据的方式,通过共享多个对象所共有的相同状态,从而让我们能在有限的内存容量中载入更多对象。从这个定义中你可以发现,享元模式要解决的核心问题就是节约内存空间,使用的办法是找出相似对象之间的共有特征,然后复用这些特征。所谓“享元”,顾名思义就是被共享的单元。比如: 一个文本字符串中存在很多重复的字符,如果每一个字符都用一个单独的对象来表示,将会占用较多的内存空间,我们可以使用享元模式解决这一类问题.

励志成为一名优秀的全能型软件开发工程师。 2245

记一次从零到getshell的渗透历程

0x00 前期 拿到测试范围清单后,首先用脚本获取了下各个子站的标题,基本都是XXX管理系统。浏览器查看后,各个子站也大同小异,纯登录系统,带验证码。这些系统基本都是jsp写的,逮到了两个没有验证码的小宝贝,一番暴力破解,小宝贝对我说:别爱我,没结果。又看到了两个站返回的Set-Cookie头:rememberMe=deleteMe; 很明显,这是Apache Shiro。打了一波exp,没有反应,放弃。搞了三天啥都没搞出来,和女朋友出去玩散散心,还是很高兴。 0x01 初显进展 测试范围内有六个门户

CanMeng'Blog - 一个WEB安全渗透的技术爱好者 3968

闲人闲谈PS之十二——WBS-BOM在装备制造项目中的实战解析

本文深入解析了WBS-BOM在装备制造项目中的核心应用。针对按订单设计/生产的行业痛点,WBS-BOM作为项目专属物料清单,完美连接SAP PS与PP模块,确保MRP能基于项目进行精准物料需求计算,实现从设计到生产的全链路项目化跟踪与管理。

weixin_29284885的博客 399

java设计模式之享元模式

java设计模式之享元模式

J_Newbie的博客 1416

大数据应用技术实验报告一 Hadoop三种模式安装配置

JDK+Hadoop安装配置、单机模式配置 以下操作在SecureCRT里面完成 1.关闭防火墙 firewall-cmd --state 显示防火墙状态running/not running systemctl stop firewalld 临时关闭防火墙,每次开机重新开启防火墙 systemctl disable firewalld 禁止防火墙服务。 2.传输JDK和HADOOP压缩包 Sec...

Ruthless_Childe的博客 3089

【Java设计模式】—— 享元模式概述和示例

围棋和五子棋中的黑白棋子,图像中的坐标点或颜色,局域网中的路由器、交换机和集线器,教室里的桌子和凳子等。这些对象有很多相似的地方,如果能把它们相同的部分提取出来共享,则能节省大量的系统资源,这就是享元模式的产生背景。

欢迎。 2143

详解GPU显存和batch size的关系

GPU显存、规格指标;神经网络训练,显存占用

orangerfun的博客 6211

Fluent新手必看:如何正确解读scaled residuals曲线(附常见问题排查)

本文详细解析了Fluent中scaled residuals曲线的解读方法及常见问题排查技巧。针对continuity残差居高不下、湍流模型收敛困难等典型问题,提供了网格质量检查、边界条件验证和求解策略调整的实用解决方案,帮助CFD新手快速掌握计算收敛性的关键判断标准。

weixin_28698059的博客 373

【设计模式】用Java实现享元模式

享元模式(Flyweight Pattern)是一种结构型设计模式旨在通过共享对象来最小化内存使用和提高性能。享元模式通过将对象的状态分为内部状态(Intrinsic State)和外部状态(Extrinsic State),并共享内部状态,从而在大量相似对象之间实现有效的资源共享。内部状态是对象可共享的、独立于对象场景的状态,它可以被多个对象共享。外部状态是对象特定的、依赖于对象场景的状态,它不能被共享,每个对象都会保持一份独立的外部状态。

分享Java硬核干货 9747

【LangChain编程:从入门到实践】实现多模态代理

【LangChain编程:从入门到实践】实现多模态代理 关键词:LangChain, 多模态代理, 自然语言处理, 机器学习, 知识图谱, 对话系统, 代码生成, AI代理 1. 背景介绍 随着人工智

欢迎来到我的优快云空间!这里聚焦AI大模型应用实战,分享前沿技术、实战案例与开发经验。 579

Java中23种设计模式的详细介绍

Java开发中23种设计模式详细介绍设计模式介绍设计模式分类设计模式六大原则开闭原则(Open Close Principle)里氏代换原则 设计模式介绍 设计模式(Design Patterns): 一套被反复使用,多数人知晓,经过分类编目,代码设计的总结 使用设计模式是为了可重用代码,让代码更容易理解,保证代码可靠性 项目中合理运用设计模式可以完美的解决很多问题,每种模式都有相应的原理...

攻城狮Chova的博客 1万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

瑞_23种设计模式_享元模式

本文章为瑞_系列专栏之《23种设计模式》的享元模式篇. 享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。JDK中Integer类使用了享元模式。

阿瑞——从事Java后端,喜欢研读源码、自研框架、分享经验 2162

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

23种设计模式之享元模式(Flyweight Pattern)

本篇文章将23种设计模式中的享元模式,此篇文章为一天学习一个设计模式系列文章,后面会分享其他模式知识。

小威的博客 2万+

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Java23种设计模式详解

提供了一种方式来封装一组具有相关联的或相互依赖的对象的创建。一个抽象工厂定义了一个接口,用于创建相关或依赖对象的家族,而实际的具体工厂则负责生成具体的对象。下面是一个使用Java实现的抽象工厂模式的简单示例:假设我们有一个图形应用程序,需要绘制不同类型的形状(如圆形、矩形等)和颜色填充策略(如红色、蓝色等)。每种形状都可以有不同的颜色填充,这就构成了两个相关的对象家族。// 抽象产品接口:形状// 具体产品:圆形@Override// 具体产品:矩形@Override。

2301_76508397的博客 3791

【Java 设计模式】结构型之享元模式

享元模式是一种结构型设计模式,旨在减少对象的数量以节省内存和提高性能。享元模式通过共享大量相似对象的状态,使得这些对象可以共享,而不需要在每个对象中都存储相同的数据。享元模式通常包含两个主要部分:享元接口和具体享元。定义了具体享元类需要实现的接口,通常包含一个方法用于接受外部状态。实现了享元接口,并存储了共享的内部状态。具体享元对象的外部状态通常通过方法参数传递进来。享元模式是一种用于减少对象数量、提高系统性能的设计模式。

好久不见的流星 1032

23种设计模式——享元模式(Flyweight Pattern)

本文介绍了23种经典设计模式之——享元模式(Flyweight Pattern)的使用及说明

Meteors.的博客 1345

【23种设计模式】结构型模式详细介绍

本文为 【23种设计模式】结构型模式 相关内容介绍,下边将对适配器模式,桥接模式,组合模式,装饰模式,外观模式,亨元模式,代理模式,具体包括它们的特点与实现等进行详尽介绍~

小新要变强的博客 1417

设计模式(十二)结构型:享元模式详解

享元模式(Flyweight Pattern)是 GoF 23 种设计模式中的结构型模式之一,其核心价值在于通过共享大量细粒度对象来有效支持大规模对象的创建与管理,从而显著减少内存占用和系统开销。

谦与谦寻的神隐 1074

全面解读Java的23种设计模式

需要注意的是,混合使用设计模式要谨慎,不要过度使用设计模式,以免代码过于复杂和难以维护。选择合适的设计模式和合适的组合方式,可以使代码更加简洁、高效和易于维护。

weixin_39158966的博客 3265

设计模式--享元模式【结构型模式】

享元模式使用优化系统性能的设计模式,享元模式的核心在于一个“享”字,也就是共享的意思,享元模式主要通过共享对象来减少系统中对象的数量,享元模式将对象分为内部状态和外部状态,内部状态的对象不会变化,外部对象会发生变化,享元模式本质就是缓存内部状态的共享对象,降低内存消耗。

weixin_42118323的博客 1454

Java23种设计模式——11.结构型模式之享元模式

Java中除去有设计原则之外,还有23中设计模式。 这些模式都是前辈们一点一点积累下来,一直在改进,一直在优化的,而这些设计模式可以解决一些特定的问题。 并且在这些模式中,可以说是将语言的使用体现的淋漓尽致。 那我们今天要学习结构型模式中的享元模式! 享元模式 我们先来了解一下享元模式,老规矩,百度百科走一走。 很感谢百度百科的介绍,但是怎么说呢,我们虽然认识每一个汉字,但是组成单词、句子之后,真的是不好读懂。 我给大家先简单的介绍一下我们为啥要用享元模式。 对弈不知道大...

胖子胖子大胖子的博客 1243

23种设计模式之享元模式

23种设计模式之享元模式

weixin_51395608的博客 1289

JAVA 23种设计模式【入门篇】

😹 作者: 爱摸鱼的小凯 😻 爱摸鱼的小凯的博客 😽 觉得博主文章写的不错的话,希望大家三连(✌关注,✌点赞,✌评论),多多支持一下!!!

只有登上山顶,才能看到那边的风光 1万+
上一篇: java23种设计模式(十) -- 外观模式(结构型设计模式)
下一篇: java23种设计模式(十二) -- 代理模式(结构型设计模式)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值