定义

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

两个状态

  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. Java异常体系结构

    1)系统错误(system error)是由Java虚拟机抛出的,用Error类表示.Error类描述的是内部系统错误.这样的错误很少发生.如果发生,除了通知用户以及尽量稳妥地终止程序外,几乎什么都不 ...

  2. JS面向对象组件(六) -- 拖拽功能以及组件的延展

    HTML部分 <div id="div1"></div> <div id="div2"></div> CSS部分 ...

  3. C++编程常见错误

    1.成员变量要记得在构造函数中初始化 2.还是初始化!初始化!初始化!

  4. hdu 5444 Elven Postman(根据先序遍历和中序遍历求后序遍历)2015 ACM/ICPC Asia Regional Changchun Online

    很坑的一道题,读了半天才读懂题,手忙脚乱的写完(套上模板+修改模板),然后RE到死…… 题意: 题面上告诉了我们这是一棵二叉树,然后告诉了我们它的先序遍历,然后,没了……没了! 反复读题,终于在偶然间 ...

  5. T-SQL:SQL Server-数据库查询语句基本查询

    ylbtech-SQL Server-Basic:SQL Server-数据库查询语句基本查询 SQL Server 数据库查询语句基本查询. 1,数据库查询语句基本查询   数据库 SQL Serv ...

  6. WCF:百度百科

    百科-WCF http://baike.baidu.com/view/1140438.htm Wcf Windows Communication Foundation(WCF)是由微软发展的一组数据通 ...

  7. hibernate建表 一对多 多的一方控制一的一方

    一对多 单向<one-to-many>通过calss操作student 外键在student表中,所以外键由student维护<many-to-one>通过student操作c ...

  8. delphi 怎么把image上的图片粘贴到剪切板上

    这个给你一个简单的代码,仅提供思路. uses Clipbrd; //引用单元 procedure TForm1.Button1Click(Sender: TObject); var Bmp: TBi ...

  9. Golang 绘图基础- 不同的输出源

    先看一个简单代码, 它执行后会产生下面的300*500的png图片文件: 代码: 1: package main 2:  3: import ( 4: "fmt" 5: " ...

  10. 【转】linux之ln命令

    转自:http://www.cnblogs.com/peida/archive/2012/12/11/2812294.html ln是linux中又一个非常重要命令,它的功能是为某一个文件在另外一个位 ...