Java设计模式(十一) 享元模式

news/2025/6/19 17:56:25

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

  原创文章,同步发自作者个人博客,http://www.jasongj.com/design_pattern/flyweight/。转载请注明出处

享元模式介绍

享元模式适用场景

面向对象技术可以很好的解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数。当对象数量太多时,将导致对象创建及垃圾回收的代价过高,造成性能下降等问题。享元模式通过共享相同或者相似的细粒度对象解决了这一类问题。

享元模式定义

享元模式(Flyweight Pattern),又称轻量级模式(这也是其英文名为FlyWeight的原因),通过共享技术有效地实现了大量细粒度对象的复用。

享元模式类图

享元模式类图如下 FlyWeight Pattern Class Diagram

享元模式角色划分

  • FlyWeight 享元接口或者(抽象享元类),定义共享接口
  • ConcreteFlyWeight 具体享元类,该类实例将实现共享
  • UnSharedConcreteFlyWeight 非共享享元实现类
  • FlyWeightFactory 享元工厂类,控制实例的创建和共享

内部状态 vs. 外部状态

  • ***内部状态***是存储在享元对象内部,一般在构造时确定或通过setter设置,并且不会随环境改变而改变的状态,因此内部状态可以共享。
  • ***外部状态***是随环境改变而改变、不可以共享的状态。外部状态在需要使用时通过客户端传入享元对象。外部状态必须由客户端保存。

享元模式实例解析

本文代码可从作者Github下载

享元接口,定义共享接口

package com.jasongj.flyweight;public interface FlyWeight {void action(String externalState);}

具体享元类,实现享元接口。该类的对象将被复用

package com.jasongj.flyweight;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class ConcreteFlyWeight implements FlyWeight {private static final Logger LOG = LoggerFactory.getLogger(ConcreteFlyWeight.class);private String name;public ConcreteFlyWeight(String name) {this.name = name;}@Overridepublic void action(String externalState) {LOG.info("name = {}, outerState = {}", this.name, externalState);}}

享元模式中,最关键的享元工厂。它将维护已创建的享元实例,并通过实例标记(一般用内部状态)去索引对应的实例。当目标对象未创建时,享元工厂负责创建实例并将其加入标记-对象映射。当目标对象已创建时,享元工厂直接返回已有实例,实现对象的复用。

package com.jasongj.factory;import java.util.concurrent.ConcurrentHashMap;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.jasongj.flyweight.ConcreteFlyWeight;
import com.jasongj.flyweight.FlyWeight;public class FlyWeightFactory {private static final Logger LOG = LoggerFactory.getLogger(FlyWeightFactory.class);private static ConcurrentHashMap<String, FlyWeight> allFlyWeight = new ConcurrentHashMap<String, FlyWeight>();public static FlyWeight getFlyWeight(String name) {if (allFlyWeight.get(name) == null) {synchronized (allFlyWeight) {if (allFlyWeight.get(name) == null) {LOG.info("Instance of name = {} does not exist, creating it");FlyWeight flyWeight = new ConcreteFlyWeight(name);LOG.info("Instance of name = {} created");allFlyWeight.put(name, flyWeight);}}}return allFlyWeight.get(name);}}

从上面代码中可以看到,享元模式中对象的复用完全依靠享元工厂。同时本例中实现了对象创建的懒加载。并且为了保证线程安全及效率,本文使用了双重检查(Double Check)。

本例中,name可以认为是内部状态,在构造时确定。externalState属于外部状态,由客户端在调用时传入。

享元模式分析

享元模式优点

  • 享元模式的外部状态相对独立,使得对象可以在不同的环境中被复用(共享对象可以适应不同的外部环境)
  • 享元模式可共享相同或相似的细粒度对象,从而减少了内存消耗,同时降低了对象创建与垃圾回收的开销

享元模式缺点

  • 外部状态由客户端保存,共享对象读取外部状态的开销可能比较大
  • 享元模式要求将内部状态与外部状态分离,这使得程序的逻辑复杂化,同时也增加了状态维护成本

享元模式已(未)遵循的OOP原则

已遵循的OOP原则

  • 依赖倒置原则
  • 迪米特法则
  • 里氏替换原则
  • 接口隔离原则
  • 单一职责原则
  • 开闭原则

未遵循的OOP原则

  • NA

Java设计模式系列

  • Java设计模式(一) 简单工厂模式不简单
  • Java设计模式(二) 工厂方法模式
  • Java设计模式(三) 抽象工厂模式
  • Java设计模式(四) 观察者模式
  • Java设计模式(五) 组合模式
  • Java设计模式(六) 代理模式 VS. 装饰模式
  • Java设计模式(七) Spring AOP JDK动态代理 vs. cglib
  • Java设计模式(八) 适配器模式
  • Java设计模式(九) 桥接模式
  • Java设计模式(十) 你真的用对单例模式了吗?
  • Java设计模式(十一) 享元模式

转载于:https://my.oschina.net/jasongj/blog/679640


https://dhexx.cn/news/show-591705.html

相关文章

JavaFx:添加顶部菜单 Microsoft Ribbon For JavaFX

JavaFx:添加顶部菜单 Microsoft Ribbon For JavaFX Microsoft Ribbon For JavaFX&#xff1a;Ribbon control for Java, implemented using JavaFX, based on the Microsoft Ribbon. Github FXRibbon FXRibbon-master 导入运行 运行ChangeAccentColorSample&#xff1a;更多内…

JavaFX:Robot高DPI截图

JavaFX:Robot高DPI截图 使用JDK中 java.awt.*&#xff1a;Robot、Rectangle JavaFX:截图功能 createScreenCapture 图片模糊 Iamge : (665.0,230.0) createMultiResolutionScreenCapture MultiResolutionImage mrImage robot.createMultiResolutionScreenCapture(rec); …

JavaFx:快捷键

JavaFx&#xff1a;快捷键 KeyCombination.html KeyCode.html 设置方式参考&#xff1a;JavaFX 设置快捷键、JavaFx&#xff1a;11、设置快捷键、JavaFX学习&#xff1a;快捷键 快捷键CTRL C KeyCombination ctrl_c new KeyCodeCombination(KeyCode.C, KeyCombination.CO…

Windows NTFS权限设置小结

在实际工作中经常会碰到NTFS文件夹权限设置的问题&#xff0c;比如&#xff1a;即使你赋予某用户full control并向子文件夹继承仍会出现access denied的情况&#xff0c;如下图&#xff1a;出现此情况的原因是由于赋权用户(如域管理员、本地管理员)没有某些子文件夹的full cont…

JavaFX: 多语言适配

JavaFX: 多语言适配 JDK国际化&#xff1a;ResourceBundle.html 其他资源&#xff1a;TornadoFX编程指南&#xff0c;第10章&#xff0c;FXML和国际化、JavaFX的ResourceBundle使用 创建Resource Bundle资源 ResourceBundle获取资源 public class ResourceBundleUtil {priva…

一组Linux Shell Scripting小练习

原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://dgd2010.blog.51cto.com/1539422/1718284 # Linux shell将字符串分割成数组 12result$(facter | awk /ipaddress/ && !/ipaddres…

PackageManagerService启动

PackageManagerService启动 android11-release SystemServer 启动 PackageManagerService 在 startBootstrapServices 中启动 PackageManagerService PackageManagerService.main() 过程主要是创建PKMS服务&#xff0c;并注册到ServiceManagerInstaller 连接 “installd” …

L2权重衰减就是L2正则化 的 代码实现

本文以Paddle为例&#xff0c;torch操作也差不多 我在5年前管这个限制参数过大的东西叫正则化&#xff0c;结果现在叫权重衰减了hhh 有点儿跟不上潮流了&#xff0c;我还以以为这个权重衰减是每次迭代给权重乘以一个0.99999&#xff0c;让他进行衰减呢(这样操作也衰减的太快了…

【转载】 HDU 动态规划46题【只提供思路与状态转移方程】

1.Robberies 连接 &#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid2955 背包;第一次做的时候把概率当做背包(放大100000倍化为整数):在此范围内最多能抢多少钱 最脑残的是把总的概率以为是抢N家银行的概率之和… 把状态转移方程写成了f[j]max{f[j],f[j-q[i].v]q…

JavaFX: HTML编辑器和加载

JavaFX: HTML编辑器和加载 Module javafx.web HTMLEditor javafx.scene.web.HTMLEditor <VBox alignment"CENTER" spacing"20.0" xmlns:fx"http://javafx.com/fxml"fx:controller"org.xhbruce.xhnote.HtmlController"><…