2025年3月31日 星期一 乙巳(蛇)年 正月初一 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > 设计模式

【设计模式】31.结构型模式-享元模式(Flyweight)

时间:02-01来源:作者:点击数:230

一、描述

  • 这是个很有意思的模式。它是通过共享技术来有效地支持大量细粒度对象的复用。

角色

  • 1)Flyweight:描述一个接口,通过这个接口flyweight可以接受并作用于外部状态
  • 2)ConcreteFlyweight:实现Flyweight接口,并为内部状态增加存储空间。ConcreteFlyweight对象必须是共享的。它所存储的状态必须是内部的。
  • 3)FlyweightFactory:创建并管理Flyweight对象。确保合理地共享flyweight。当用户请求一个flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个
  • 4Client:维持一个对flyweight的引用。计算或存储一个flyweight的外部状态。

类图

在这里插入图片描述
  • 享元模式的特点有两个
  • (1)内在状态:用于创建对象。
  • (2)外在状态:外界传给实例的参数,用于实例执行某些方法。

如何理解享元模式?

刚开始看享元模式,这个模式感觉和单例模式很类似,两者区别是单例模式的关注点是创建单一对象,享元模式的关注点是规划创建对象。

享元模式不太好理解,它的难点在于理解它的结构以及为什么会创造出这样的设计结构。我从一本书上的享元模式的例子中理解了享元模式的目的以及实现。书中的例子是以“文档编辑器”加载数据为例:

通常上,文档编辑器上的文字或者字母,每个文字、字母都应该有一个存储

在这里插入图片描述

但是在物理结构上,却是相同的文字、字母共享同一个flyweight对象,从一个池中取数据,这种加载模式就是享元模式。

在这里插入图片描述

二、优点

  • (1)减少对象的创建,降低系统的内存,使效率提高。

三、缺点

  • 网上都说下面的是缺点,我并不这样认为,这是享元模式的特点。除了创建对象需要工厂外,内部外部状态也是其特点之一。
  • (1)享元模式需要区分出内部状态和外部状态,内部状态不可查看,外部状态是对象方法执行的参数,是客户赋予对象的,是可见的。外部状态在不同内部状态的对象下的方法中执行,可能产生不同的结果。

四、使用场景

  • (1)一个应用程序使用了大量的对象
  • (2)完全由于使用大量的对象,造成很大的存储开销
  • (3)对象的大多数状态都可变为外部状态
  • (4)如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象
  • (5)应用程序不依赖于对象标识,由于Flyweight对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。

五、示例

模拟文档编辑器,写了一个简单的文字加载程序。如下:

1.抽象享元类

定义加载字体的抽象方法

  • public abstract class Flyweight {
  • /**
  • * 加载字体
  • *
  • * @param fontAttribute
  • */
  • abstract String load(FontAttribute fontAttribute);
  • }

2.文字属性类

定义文字的属性

  • @Data
  • public class FontAttribute {
  • /**
  • * 字体颜色:30黑 31红 32绿 33黄 34蓝 35紫 36深绿 37白
  • */
  • private Integer color;
  • /**
  • * 字体格式:0重置 1加粗 2减弱 3斜体 4下划线 5慢速闪烁 6快速闪烁
  • */
  • private Integer fontType;
  • }

3.具体文字类

定义加载字体的实现方法,以及文字标志量

  • public class Font extends Flyweight {
  • //文字为内在属性
  • private String word;
  • public Font(String word) {
  • this.word = word;
  • }
  • /**
  • * 加载字体,FontAttribute为外在属性
  • *
  • * @param fontAttribute
  • */
  • @Override
  • public String load(FontAttribute fontAttribute) {
  • //格式化字体属性
  • return String.format("\033[%d;%dm%s\033[0m",fontAttribute.getColor(),fontAttribute.getFontType(),this.word);
  • }
  • }

4.文字工厂类

定义创建文字的方法

  • public class FontFactory {
  • HashMap<String, Font> fontHashMap = new HashMap<>();
  • /**
  • * 造字
  • *
  • * @param word
  • * @return
  • */
  • public Font createFont(String word) {
  • //如果map中有该文字,则直接获取,不需要创建
  • if (fontHashMap.containsKey(word)) {
  • return fontHashMap.get(word);
  • }
  • //若map中不存在该文字,则造字
  • return new Font(word);
  • }
  • }

5.Client

定义调用方法

  • public class Client {
  • public static void main(String[] args) {
  • FontFactory factory = new FontFactory();
  • //文字
  • String[] words = {"h", "e", "l", "l", "o", "w", "o", "r", "l", "d"};
  • //颜色编码
  • Integer[] colors = {30, 31, 32, 33, 34, 35, 36, 37};
  • //字体格式
  • Integer[] fontTypes = {0, 1, 2, 3, 4, 5, 6, 7};
  • for (int i = 0; i < words.length; i++) {
  • Font font = factory.createFont(words[i]);
  • FontAttribute attribute = new FontAttribute();
  • //设置字体属性
  • attribute.setColor(colors[i % colors.length]);
  • attribute.setFontType(fontTypes[i % fontTypes.length]);
  • //打印文字
  • System.out.print(font.load(attribute));
  • }
  • }
  • }

效果:

在这里插入图片描述
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门