结构型设计模式(五) 之 享元模式是池技术的表现
1 定义
享元模式(Flyweight Pattern)属于结构型设计模式之一,它主要是使用共享对象有效地避免了创建过多的性质相近的对象,从而降低内存的占用,提高程序的性能。它也是池技术的重要实现方式,正如常量池、数据库连接池、缓冲池等都是享元模式的应用。享元模式一般结合工厂模式一起使用,在获取对象时会尝试使用共享的已存在的同类对象,如果未能匹配到对象才再去创建新对象。这些对象分为两个部分:内部状态和 外部状态:
内部状态,是对象内部可共享的信息,它并不会因外部环境改变而发生改变。
外部状态,是对象外部使用的一个标记,它会因外部环境改变而发生改变并且不可共享的状态。
例如现实场景中,某品牌手机有内存128G、256G和512G的版本区分,所以这手机对象有手机型号和内存版本两个字段,其中手机型号就是它的内部状态,而内存版本就是它的外部状态。现在我们需要对这手机进行量产各100台,那么我们当然不需要去重复设计和适配3*100个台,因为其仅不同点只在于内存版本的不同,所以只需要专门的部门研发出3台不同内存版本的样板机,其余的就按思路复制生产即可,这个思路就是享元模式。
2 实现
享元模式一般包含3个角色,分别是:
- 抽象享元(Flyweight),就是具体享元的抽象类,用于定义对象的内部状态和外部状态的接口或者实现。例如上述定义举例的手机统称,它定义出手机型号、手机内存版本等内部和外部状态。
- 具体享元(ConcreteFlyweight),就是实现抽象享元定义的业务。例如上述定义举例的具体的样板手机。
- 享元工厂(FlyweightFactory),就是负责管理对象池和创建享元对象。例如上述定义举例的提供样板机的部门。
抽象享元类,它是手机的统称和手机字段的定义:
public abstract class Phone {protected String mModel;protected String mMemory;protected abstract void showInfo();
}
具体享元,它继承于抽象享元类,是具体的样板手机:
public class ApplePhone extends Phone {public ApplePhone(String memory) {mModel = "IPhone99";mMemory = memory;}@Overrideprotected void showInfo() {System.out.println(mModel + "很牛逼,内存是:" + mMemory);}
}
享元工厂,通过一个Map的私有变量来保存已经创建过的对象:
public class PhoneFactory {private static Map<String, Phone> phonePool = new HashMap<>();public static Phone getPhone(String memory) {if (phonePool.containsKey(memory)) {System.out.println("缓存返回对象,key是:" + memory);return phonePool.get(memory);} else {Phone phone = new ApplePhone(memory);phonePool.put(memory, phone);System.out.println("新创建对象,key是:" + memory);return phone;}}
}
客户端:
Phone phone1 = PhoneFactory.getPhone("128G");
phone1.showInfo();Phone phone2 = PhoneFactory.getPhone("256G");
phone2.showInfo();Phone phone3 = PhoneFactory.getPhone("512G");
phone3.showInfo();Phone phone4 = PhoneFactory.getPhone("256G");
phone4.showInfo();
输出结果:
新创建对象,key是:128G
IPhone99很牛逼,内存是:128G
新创建对象,key是:256G
IPhone99很牛逼,内存是:256G
新创建对象,key是:512G
IPhone99很牛逼,内存是:512G
缓存返回对象,key是:256G
IPhone99很牛逼,内存是:256G
3 区别
3.1 与原型模式的区别
享元模式与原型模式非常相似,它们都是为了解决重复创建对象的性能优化方案,我们来聊了儿它们的区别:
- 原型模式是在直接创建对象的代价比克隆更大时通过克隆来解决重复创建的问题;享元模式是在对创建过多的性质相似的对象时通过缓存来解决重复创建的问题。
- 原型模式创建的对象属性完全一样,而享元模式会根据不同的外部状态创建不一样的对象实例。
3.2 与单例模式的区别
享元模式还与懒加载式的单例模式非常相似,它们都是先尝试从内存中获得已创建好的对象,如果未能获取再去创建新对象并进行缓存于内存中,我们又来聊聊它们的区别:
- 单例模式是出于共享对象状态为目的,而享元模式是为了节省内存空间为目的。
- 单例模式是针对一个类的单例,一般会严格控制一个进程只有一个实例,而享元模式不严格控制实例个数,可以针对一个类的不同表现形式的多个单例。
4 总结
既然享元模式是产生对象,为什么不是创建型设计模式而是结构型设计模式呢?因为享元模式是提供了减少对象数量从而改善应用所需的对象结构的方式,所以它被归类到结构型设计模式中。享元模式的初衷是节省内存空间,它对于重复的对象只会被创建一次,适用于需要创建很多性质相近的重复对象的场景。不过要注意的是享元工厂中池容量需要做最值的限制,否则会因为希望节省内存反而让缓存池把内存给占满了。享元模式节省了内存空间,但提高了系统的复杂度,需要明确分离享元业务的外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
结构型设计模式(五) 之 享元模式是池技术的表现相关推荐
- Java描述设计模式(18):享元模式
本文源码:GitHub·点这里 || GitEE·点这里 一.使用场景 应用代码 public class C01_InScene {public static void main(String[] ...
- 设计模式(十五)享元模式(结构型)
概述 当一个软件系统在运行时产生的对象数量太多,将导致运行代价过高,带来系统性能下降等问题.例如在一个文本字符串中存在很多重复的字符,如果每一个字符都用一个单独的对象来表示,将会占用较多的内存空间,那 ...
- C#设计模式之十一享元模式(Flyweight Pattern)【结构型】
一.引言 今天我们要讲[结构型]设计模式的第六个模式,该模式是[享元模式],英文名称是:Flyweight Pattern.还是老套路,先从名字上来看看."享元"是不是可以这样理解 ...
- GoF设计模式(十二) - 享元模式
前言 享元模式(Flyweight Pattern)运用共享技术有效地支持大量细粒度的对象,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的 ...
- 【设计模式自习室】享元模式 Flyweight Pattern:减少对象数量
前言 <设计模式自习室>系列,顾名思义,本系列文章带你温习常见的设计模式.主要内容有: 该模式的介绍,包括: 引子.意图(大白话解释) 类图.时序图(理论规范) 该模式的代码示例:熟悉该模 ...
- 设计模式八(享元模式)
享元模式 面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数.当对象数量太多时,将导致运行代价过高,带来性能下降等问题.享元模式正是为解决这一类问题而诞生 ...
- Net设计模式实例之享元模式( Flyweight Pattern)
一.享元模式简介(Brief Introduction) 享元模式(Flyweight Pattern),运用共享技术有效支持大量细粒度的对象. Use sharing to support larg ...
- 结构型设计模式(二) 之 装饰者模式可给对象一层层加工
1 定义 装饰者模式(Decorator Pattern)又叫包装模式属于结构型设计模式之一,它主要用于动态地给一个对象增加一些额外扩展的功能,它是继承关系的一个替代方案,且在特定场景中比使用继承生成 ...
- 《研磨设计模式》chap20 享元模式 Flyweight (4)总结
1. 不共享的外部状态 输入数据为: 张三,人员列表,查看,1 李四,人员列表,查看,1 李四,操作薪资数据,2 " 操作薪资数据"包括"薪资数据,查看",&q ...
最新文章
- Swift 中使用 SQLite——批量更新(事务处理)
- 昨天晚上,亲眼目睹了我一哥们的崩溃,被空降90后上司鄙视,说他这种人在公司......
- SAP MM 物料主数据里的‘Packaging Material Type‘字段
- 干货丨卷积神经网络工作原理的直观解释
- docker api 基本介绍和使用
- python课程将主要介绍哪些内容-熊学堂 · 人工智能 | 课程介绍
- Oracle PL/SQL 非预定义异常、自定义异常处理、RAISE_APPLICATION_ERROR
- Linux下最简单的修改文件名后缀的命令行技巧
- JavaScript 刷新当前页面
- 二叉搜索树(排序二叉树)
- ASP.NET MVC3 Model验证总结
- 2018-2019-2 20175320实验五《网络编程与安全》实验报告
- PIC16F887 实战编程 单片机编程 基础实验教程
- 支撑马蜂窝「双11」营销大战背后的技术架构 营销活动优惠券架构设计
- 耗纸古文风之四--登高
- c语言为什么不能自动free,求大神帮忙看看 为什么cfree没有报错但是就是运行不了...
- AP 计算机 真知源自实践,盛誉源自读者;孜孜不倦,止于至善---林振营老师编著的中国第一套 AP计算机教材学生评价
- 轻量级服务器和ECS云服务器有什么区别?
- 关于win7升级win10后高分屏界面显示模糊问题,字迹显示模糊问题解决办法
- win8.1老是断网LOL老是掉线.net错误 问题集(win7适用)
热门文章
- 机器学习数学基础之统计篇——概率论(python版)
- Android面试中多说这么一句话,薪水直接涨5k,flutter面试题2021
- Java项目:水果生鲜超市商城管理系统(java+SSM+JSP+jQuery+Mysql)
- MATLAB图形界面设计
- 中国记忆床垫行业盈利情况及未来需求前景预测报告(新版)2022-2027年
- nmf java_NMF pLSA
- Android实现滑动屏幕切换图片
- linux vps备份脚本,vps自动备份shell脚本代码
- 知识图谱可视化——Neo4j (windows)
- 如何在FPGA中构建数控振荡器 (NCO)