定义

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

两个状态

  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. Oracle 11gR2用gpnp profile存放ASM的spfile路径

    从Oracle 11gR2开始,GI集成了ASM,OCR/VOTEDISK也存放在ASM磁盘组了(11gR2以前需要存放于裸设备中),同时ASM的功能较10g也有很大增强. 我们先引入一个问题:11g ...

  2. 热门Web开发方式 REST实现原理浅析

    REST 首先只是一种架构样式,不是一种标准.这点和 Ajax 类似,两者都是利用现有的成熟技术.在 REST 的定义中,一个 Web 应用总是使用固定的 URI 向外部世界呈现(或者说暴露)一个资源 ...

  3. 关于用netbeans和xdebug调试php的配置

    之前用过一段时间在apache,netbeans下通过xdebug调试.感觉不错,最近事情不多想从新配置下,是基于最新版本的php5.4做的,后来参考了下xdebug的官网说明完成的.官网地址:htt ...

  4. 又一枚神器:nginx

    一直听说过nginx的大名,也自己装过,但是未直接使用其各种牛X的功能. 今天试用了一下,只能用两字感叹:牛逼!比如它提供的配置检查功能,真是贴心极了,又比如我想要的静态内容浏览器端缓存功能,动态内容 ...

  5. python27+django创建app

    python manage.py startapp polls创建一个叫polls的app 编辑文件 polls/models.py : 1 from django.db import models ...

  6. ansible条件使用--实践

    ansible条件使用 1.条件使用最简单的方式 ansible中使用条件最简单的方式如下所示: [root@ansibleserver kel]# cat conditions.yml --- - ...

  7. 【LeetCode】66 & 67- Plus One & Add Binary

    66 - Plus One Given a non-negative number represented as an array of digits, plus one to the number. ...

  8. [转载]我读过最好的Epoll模型讲解

    转载来自:http://blog.csdn.net/mango_song/article/details/42643971 首先我们来定义流的概念,一个流可以是文件,socket,pipe等等可以进行 ...

  9. web.xml 配置介绍

    这个不是原创,有点早了,具体从哪里来的已经记不得了.但是东西是实实在在的. 1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<c ...

  10. 前端技能汇总 Frontend Knowledge Structure

    Frontend Knowledge Structure 项目起源 还记得@jayli 的这幅前端知识结构图么. 图片的形式具有诸多的不便.缺失源图的我们,无法为此图贡献些什么,随着时间的迁移,或许有 ...