享元模式是对象池的一种实现,它的英文名称叫做Flyweight,代表轻量级的意思。享元模式用来尽可能减少内存使用量,它适合用于可能存在大量重复对象的场景,来缓存可

共享的对象,达到对象共享、避免创建过多对象的效果,这样一来就可以提升性能、避免内存移除等。

享元对象中的部分状态是可以共享,可以共享的状态成为内部状态,内部状态不会随着环境变化;不可共享的状态则称之为外部状态,它们会随着环境的改变而改变。在享元

模式中会建立一个对象容器,在经典的享元模式中该容器为一个Map,它的键是享元对象的内部状态,它的值就是享元对象本身,。客户端程序通过这个内部状态从享元工厂中获取

享元对象,如果有缓存则使用缓存对象,否则创建一个享元对象并且存入容器中,这样一来就避免了创建过多对象的问题。

定义

使用共享对象可有效地支持大量的细粒度的对象。

使用场景

1.系统中存在大量的相似对象。

2.细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身价。

3.需要缓冲池的场景。

UML类图

Flyweight :享元对象抽象基类或者接口

ConcreteFlyweight :具体的享元对象。

FlyweightFactory :享元工厂,负责管理享元对象池和创建享元对象。

示例

用买火车票做为例子,无数人用刷票软件在向服务端发出请求,对于每个请求服务器都必须做出应答。在用户设置好出发地和目的地之后,每次请求都返回一个的车票结果,假设每次返回的只有一躺列车的车票。那么当数以万计的人不间断的请求数据时,如果每次都重新创建一个的车票结果,那么必然会造成大量重复对象的创建、销毁,使得

GC任务繁重、内存占用率高居不下。从A到B的车辆是有限的,车上的铺位也就那么几种,我们将这些可以公用的对象缓存起来,在用户查询时优先使用缓存,如果没有缓存则重新创建,这样就将成千上万的对象变为了可选择的有限数量。

public interface Ticket {//展示车票信息的方法public void showTicketInfo(String bunk);
}
//火车票类
public class TrainTicket implements Ticket{public String from; //始发地public String to;   //目的地public String bunk; //铺位public int price;public TrainTicket(String from, String to) {this.from = from;this.to = to;}@Overridepublic void showTicketInfo(String bunk) {price = new Random().nextInt(300);System.out.println("购买从" + from + "到" + to + "的" + bunk + "火车票" + ",价格 : " + price);}}

享元模式通过消息池的形式有效地减少了重复对象的存在,它通过内部状态标识某个种类的对象,外部程序根据这个不会变化的内部状态从消息池中取出对象。使得同一类对象可以被复用,避免大量重复对象。

public class TicketFactory {static Map<String,Ticket> sTicketMap = new ConcurrentHashMap<String,Ticket>();public static Ticket getTicket(String from, String to){String key = from + "-" + to;if(sTicketMap.containsKey(key)){System.out.println("use cache : " + key);return sTicketMap.get(key);}else {System.out.println("create object : " + key);Ticket ticket = new TrainTicket(from, to);sTicketMap.put(key, ticket);return ticket;}}//我们在TicketFactory添加了一个map容器,并且以出发地“-”目的地为键、以车票对象作为值存储车票对象。这个map的键就是我们说的内部状态,如果没有缓存则创建一个对象,并且将这个对象//缓存到map中,下次再有这类请求时则直接从缓存中获取。这样即使有10000个请求北京到青岛的车票信息,那么出发地是北京,目的地是青岛的车票对象只有一个。这样就从这个对象从10000减到了1个,//避免了大量的内存占用及频繁的GC操作。
}
public class Client {public static void main(String[] args) {Ticket tick1 = TicketFactory.getTicket("北京", "青岛");tick1.showTicketInfo("上铺");Ticket tick2 = TicketFactory.getTicket("北京", "青岛");tick1.showTicketInfo("中铺");Ticket tick3 = TicketFactory.getTicket("北京", "青岛");tick1.showTicketInfo("下铺");}//运行结果:/*create object : 北京-青岛购买从北京到青岛的上铺火车票,价格 : 154use cache : 北京-青岛购买从北京到青岛的中铺火车票,价格 : 101use cache : 北京-青岛购买从北京到青岛的下铺火车票,价格 : 59*/
}

从结果可以看出,只有第一次查询车票时创建了一次对象,后续的查询都使用的是消息池中的对象。这其实就是相当于一个对象缓存,避免了对象的重复创建与回收。

总结

享元模式实现比较简单,但是它的作用在某些场景确实极其重要。它可以大大减少应用程序创建的对象,降低程序内存的占用,增加程序的性能,但它同时也提高了系统的复杂性,需要分离出外部状态和内部状态,而且外部状态具有固化特性,不应该随内部改变而改变,否则导致系统的逻辑混乱。

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

缺点

1.享元模式使得系统更加复杂,为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。

2.享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。

[设计模式]享元模式相关推荐

  1. Python设计模式-享元模式

    Python设计模式-享元模式 基于Python3.5.2,代码如下 #coding:utf-8class Coffee:name = ""price = 0def __init_ ...

  2. 10-Python与设计模式--享元模式

    10-Python与设计模式--享元模式 一.网上咖啡选购平台 假设有一个网上咖啡选购平台,客户可以在该平台上下订单订购咖啡,平台会根据用户位置进行线下配送.假设其咖啡对象构造如下: class Co ...

  3. 设计模式--享元模式实现C++

    /********************************* *设计模式--享元模式实现 *C++语言 *Author:WangYong *Blog:http://www.cnblogs.co ...

  4. 【设计模式】Java设计模式 - 享元模式

    [设计模式]Java设计模式 - 享元模式

  5. Unity设计模式——享元模式(附代码)

    Unity设计模式--享元模式(附源码) 享元Flyweight模式是什么 享元模式是一种结构型设计模式, 它摒弃了在每个对象中保存所有数据的方式, 通过共享多个对象所共有的相同状态, 让你能在有限的 ...

  6. 第二十二章 Caché 设计模式 享元模式

    文章目录 第二十二章 Caché 设计模式 享元模式 定义 优点 使用场景 结构图 描述 完整示例 实体类 抽象享元角色 实现享元角色 享元工厂 调用 思考 第二十二章 Caché 设计模式 享元模式 ...

  7. JavaScript设计模式-享元模式

    JavaScript设计模式-享元模式 概念 例子 内部状态与外部状态 享元模式的通用结构 例子 总结 github仓库地址:点击 [设计模式例子](https://github.com/fanhua ...

  8. JAVA 设计模式 享元模式

    用途 享元模式 (Flyweight) 运用共享技术有效地支持大量细粒度的对象. 享元模式是一种结构型模式. 结构 图-享元模式结构图 Flyweight : 它是所有具体享元类的超类或接口,通过这个 ...

  9. java设计模式---享元模式

    Java深入到一定程度,就不可避免的碰到设计模式这一概念,了解设计模式,将使自己 对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广 泛,遵循一定的编程模式,才能使自己的 ...

  10. PHP设计模式——享元模式

    声明:本系列博客参考资料<大话设计模式>,作者程杰. 享元模式使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件:它适合用于只是因重复而导致使用无法令人接受的大量内存的 ...

最新文章

  1. 数据库读取image类型发送到前端显示图片
  2. Git同步本地项目文件到github
  3. [转载] Java面试题大全(2020版)
  4. 近期可能会研究和讨论的个人动向
  5. clion 插件_IDEA必备插件系列-Rainbow
  6. Google Puppeteer加入到headless Chrome的工具行列
  7. 2018年计算机基础模拟试题,2018年大学计算机基础试题及答案
  8. XML PUBLISHER输出excel存在科学计数
  9. Mac桌面上找不到或无法显示USB问题
  10. 三、spring中高级装配(1)
  11. 基于java的宠物领养交流网站
  12. 印象笔记三级目录_如何建立印象笔记的三层目录构架
  13. html 星星字体,做华丽的星星文字效
  14. 下载B站、秒拍等视频网站视频
  15. kubernetes 核心组件之 Controller Manager
  16. mongodb 创建只读用户
  17. 从零开始 教你如何搭建Discuz!4.1论坛(图)
  18. Codeforces Round #516 E. Dwarves, Hats and Extrasensory Abilities
  19. python中screen用法_screen命令的使用
  20. 抖~~音 无水印video 下载

热门文章

  1. java解决properties中中文乱码问题
  2. Excel:将图片制作成九宫格形式
  3. 大赛通知|12万奖金!BMW宝马发起编程新赛事,四大赛道等你挑战!
  4. 超声波电路板驱动线路设计
  5. python3.9安装_Python 3.9下载 Python 3.9.0 for Windows 官方安装正式版 32位/64位 下载-脚本之家...
  6. JDK动态代理学习笔记
  7. 2345安全卫士卸载不了怎么办?
  8. endnote转化为文字格式
  9. pythonif语句如何循环_pythonif语句如何循环
  10. 关于JDBC连接MySQL的时候出现警告:Establishing SSL connection without server‘s identity verification is not recom