定义

运用共享技术有效的支持大量细粒度的对象。

两个状态

  1. 内蕴状态存储在享元内部,不会随环境的改变而有所不同,是可以共享的。
  2. 外蕴状态是不可以共享的,它随环境的改变而改变的,因此外蕴状态是由客户端来保持(因为环境的变化是由客户端引起的)。

和对象池的区别

  1. 对象池主要解决对象的复用问题,池中的每个对象都是可以替换的,从池中获取对象A和获取对象B对客户端而言都是一样的。
  2. 享元模式主要解决对象的共享问题,建立多个细粒度的可以进行共享的对象是其关注的重点。

UML

优点

  1. 减少运行时对象实例的个数,节省内存。
  2. 将许多“虚拟”对象的状态集中管理。

缺点

  1. 一旦你实现了它,单个的逻辑实现将无法拥有独立而不同的行为。

应用场景

  1. 系统中有大量对象且这些对象消耗大量内存。
  2. 这些对象的状态大部分可以外部化。
  3. 这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。

示例

我们考虑一个场景,当我们需要自己实现绘制艺术字时,每一个字符都会有下面的几个状态:1.字体轮廓(这部分就是最耗内存的部分,每个字体都会有大量的数据来记录该字体的样式);2.字体字符(标志该字体用来表示哪一个字符);3.字体大小;4.字体位置。

当我们使用该艺术字来呈现一堆文本时,如果每个字符都加载同一份轮廓则会对内存和GC造成压力。

我们会发现对于同一个字符来说,轮廓和字符都是一致的内部状态,而大小和位置则是会变动的外部状态;我们通过使用享元模式来节省内存的使用;

Java

 import java.util.HashMap;
import java.util.Map; public class Main
{
public static void main(String[] args)
{
String text = "Hello World! Hello Flyweight!";
for (int i = 0; i < text.length(); i++)
{
char c = text.charAt(i);
FontFlyweight font = (FontFlyweight) FontFlyweightFactory.getFont(c);
font.size = (int) ((Math.random() * 20) + 7);
font.x = (int) ((Math.random() * 500));
font.y = (int) ((Math.random() * 500));
font.drawFont();
}
FontFlyweightFactory.printFontCount();
} /**
* 字体享元接口
*/
public interface IFontFlyweight
{
/**
* 绘制当前字体
*/
void drawFont();
} /**
* 字体享元类
*/
public static class FontFlyweight implements IFontFlyweight
{
/**
* 不会改变可以共享的内部状态
*/
public final char symbol;
public final String font; /**
* 频繁改变不可以共享的外部状态
*/
public int size;
public int x;
public int y; public FontFlyweight(char symbol)
{
this.symbol = symbol;
//这里一般会从硬盘读取指定的美术字的字体样式
this.font = "自定义的美术字";
} @Override
public void drawFont()
{
//实际上绘制一个指定样式的矢量字符是非常复杂的,内存中需要保存该字符的所有矢量信息,会占用比较大的内存开销
System.out.println("在位置(" + x + ", " + y + ")处使用字体\"" + font + "\"绘制\"" + size + "\"号尺寸的字符\"" + symbol + "\"");
}
} /**
* 字体享元工厂
*/
public static class FontFlyweightFactory
{
private static Map<Character, IFontFlyweight> _map = new HashMap<>(); /**
* 根据外部状态获取对应的享元对象
*/
public static IFontFlyweight getFont(char key)
{
if(_map.containsKey(key))
{
return _map.get(key);
}
IFontFlyweight info = new FontFlyweight(key);
_map.put(key, info);
return info;
} public static void printFontCount()
{
System.out.println("内存中存在的字体实例数量:" + _map.values().size());
}
}
}

结构类模式(六):享元(Flyweight)的更多相关文章

  1. 结构型模式(六) 享元模式(Flyweight)

    一.动机(Motivate) 在软件系统中,采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价--主要指内存需求方面的代价.如何在避免大量细粒度对象问题的同时,让外 ...

  2. 十一、结构模式之享元(Flyweight)模式

    什么是享元模式 享元模式是对象的结构模式,是运用共享技术来有效的支持大量细粒度的对象.享元对象能做到共享的关键是区分内蕴状态和外蕴状态.一个内蕴状态是存储在享元对象内部,并且是不会随环境改变而有所不同 ...

  3. 十二、享元(Flyweight)模式--结构模式(Structural Pattern)

    Flyweight在拳击比赛中指最轻量级,即"蝇量级",有些作者翻译为"羽量级".这里使用"享元 模式"更能反映模式的用意. 享元模式以共享 ...

  4. 七个结构模式之享元模式(Flyweight Pattern)

    定义: 运用共享技术对大量细粒度对象的复用,这要求这些对象都很相似,状态变化很小.将这些对象的内部状态和外部状态进行区分,对于内部状态相同的只存储一个对象,而对不同的外部状态则采用不同的操作. 结构图 ...

  5. 享元(FlyWeight)模式

    享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式.享元模式尝试 ...

  6. Java 实现享元(Flyweight)模式

    /** * 字母 * @author stone * */ public class Letter { private String name; public Letter(String name) ...

  7. 设计模式GOF23(结构型模式:代理模式,适配模式,桥接模式,组合模式,装饰模式,外观模式,享元模式)

    结构型模式: – 分类: • 适配器模式.代理模式.桥接模式.装饰模式.组合模式.外观模式.享元模式 – 核心作用:是从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题.   结构 ...

  8. 设计模式之结构类模式大PK

                                      结构类模式大PK 结构类模式包括适配器模式.桥梁模式.组合模式.装饰模式.门面模式.享元模式和代理模式.之所以称其为结构类模式,是因 ...

  9. 设计模式之结构类模式PK

    结构类模式包括: 适配器模式 桥梁模式 组合模式 装饰模式 门面模式 享元模式 代理模式 结构类模式着重于如何建立一个软件结构 为什么叫结构类模式呢? 因为他们都是通过组合类或对象产生更大结构以适应更 ...

随机推荐

  1. 【转】strcpy溢出的攻击示例

    在学习c/c++的时候,就讲到了一些C类型的字符串函数不是安全的,比如strcpy没有检查长度会溢出,推荐使用strncpy,笔试面试也经常问到.同时经常浏览安全相关的新闻,缓冲区溢出攻击是很常见的一 ...

  2. 梯度下降之随机梯度下降 -minibatch 与并行化方法

    问题的引入: 考虑一个典型的有监督机器学习问题,给定m个训练样本S={x(i),y(i)},通过经验风险最小化来得到一组权值w,则现在对于整个训练集待优化目标函数为: 其中为单个训练样本(x(i),y ...

  3. Android Studio 学习 - HelloWorld

    今天是学习Android Studio的第2天,加油! 1. 首先要记录下使用Android Studio的一个代码自动完成的功能.平常基本上用Delphi,乍一换工具,各种不习惯,或者说不熟悉.按照 ...

  4. RBAC(Role-Based Access Control,基于角色的访问控制)

    RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干权限.这样,就构造成“用户-角色- ...

  5. xcode的ios工程目录结构

    目录结构: a.supporting files: main.m和资源文件 xxx-info.plist:包含应用程序相关属性列表,如版本,程序名等 .pch文件:预编译头文件,相当于MFC里的std ...

  6. $(function(){})和jQuery(function(){})

    $(function(){})和jQuery(function(){})有没有区别,群里的屌丝争吵起来,各自讲着各种理论大道理.但还是有人给出了简而有力的证明: 区分大小写(jQuery) 但jQue ...

  7. 可以用google了

    半年都上不了google,现在可以了, 哈哈,支持自动更新, 有时候用google还是很不错的,尤其是英文搜索.

  8. MySQL · 引擎特性 · InnoDB 崩溃恢复过程

    MySQL · 引擎特性 · InnoDB 崩溃恢复过程 在前面两期月报中,我们详细介绍了 InnoDB redo log 和 undo log 的相关知识,本文将介绍 InnoDB 在崩溃恢复时的主 ...

  9. 平庸与卓越的差别 z

    本文是清华大学陈吉宁校长于在 2015 年第一次研究生毕业典礼暨学位授予仪式上的讲话,原文标题:选择与坚持.演讲非常精彩,值得您细细阅读. 亲爱的同学们: 今天,共有 1318 名同学获得博士.硕士学 ...

  10. 【PHP】linux搭建PHP运行环境

    之前在windows下写了hello world,终归是不够用啊,因为开发环境是Linux,怎么办呢~~~学习学习再学习 写在前面的话:我从百度文库的一个文章里摘出来的,原文章名称<Linux下 ...