摘要:

1.本文将详细介绍享元模式的原理和实际代码中特别是Android系统代码中的应用。

纲要:

1. 引入享元模式

2. 享元模式的概念及优缺点介绍

3. 享元模式在Android源码中的应用

1.先来一个段子:

GG每天给MM至少发一条短信,而且每天入睡前是必有一条短信的,往往是一些琐事和一些比较肉麻的情话。开始的一个月,GG还对此是乐不可支,随着时间的推移,那些肉麻的话说了很多遍,自己也觉得厌烦了,而且更让人不可忍耐的是这些肉麻的情话每次都要重复的输入。GG把这一烦心事告诉了自己的好友K,K说,“你这个大傻瓜,怎么不把一些你常用的话存放在你的手机中,这样,要用的时候,直接拿来用就行了”,傻GG一听,顿时觉得醍醐灌顶,于是立即在手机中存放入了“宝贝儿,晚安喔”、“你是我天使”,“宝贝儿,我永远的爱你”等话语。(摘自Android大话设计模式)

2.享元模式介绍

2.1什么是享元模式?

为了节约内存资源,把具有重复性质的实例进行统一管理(结合Factory模式),使用时对象一般不创建新实例,只进行引用。Flyweight本是体育上的一个术语,用来表示轻量级。Flyweight,飞翔般的重量,说明使用它会使代码变得“轻”(指内存消耗方面)起来。

2.2享元模式有什么好处?

上面已经提到了,它最大也是唯一的好处就是:“轻”。享元能够节省重复实例的内存消耗。举两个最经典的例子。

1、26个英文字母的点阵显示数据。我们使用它们的时候,如果每次使用都创建新的字母实例,那内存浪费是很严重的。我们可以很容易的想到,将这26个点阵数据个创建一个实例,并专门用一个类管理起来。当用户需要使用的时候,给他们这些实例的引用,这样就能大大节省内存消耗了。

2、画画。假设我能画的图形是有限的(圆,长方形,棱形,梯形等),画画就是把这些图形不断的往上贴图。当我一幅画有上千个图案的时候,享元模式就成为了很好的减少内存消耗的解决方案。我们把固定的图形都只创建一个实例,等要画的时候,使用它们的引用“作画”即可。

不过这个画画的例子就有问题了:这些独立图形的位置,大小,颜色都不一样,而实例只有一个,这样画出来岂不是都挤一块去了?这里是享元模式的关键的地方:区分内蕴态和外蕴态。简单说就是:一部分(图形)共享(称为内部储存或内部状态),一部分(大小,位置,颜色)不公享(称为外部储存或外部状态)。把这个概念加进去,享元模式就灵活多了。

3.源码实战:

3.1String

没想到吧!String用到了享元模式。其实我也没想到。就我个人理解,与其说String使用享元模式,不如说是用到了它的思想,毕竟它的实现不是通过活生生的Java代码。下面一起来看一下:

String s0=”abc”;String s1=”abc”;String s2=”a” + “bc”;System.out.println( s0==s1 );System.out.println( s0==s2 );

结果为:

truetrue

我们都知道,String是一种对象(非基础类型,下同),对象的==比较的是和指向的内存有关的。如果两个对象指向的是同一个数据,那他们是相等的(Java语言是不支持重载的,所以没有例外情况)。

但上面的写法不应该是三个独立的数据段吗?这里就涉及到常量池。

常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。 这些字符串对于编译器来说,都是同样的常量字符串,所以编译器把他们简化成了一条数据,从而优化了内存使用。这和享元模式的思想如出一辙。

如果我们这样写:

String s0=”abc”;String s1= new String(“abc”);System.out.println( s0==s1 );

结果为:

false

为什么会这样?因为s1等号右边不是常量字符串,而是实例化操作,人家编译器不认这种非静态的东西。这也说明了一点,享元需要专门的类来管理,否则就会出现上面那种不适用的情况。一般来说都是用Factory。

3.2SQLiteCompiledSql

(参考Android设计模式系列(6)--SDK源码之享元模式 http://www.cnblogs.com/qianxudetianxia/archive/2011/08/10/2133659.html)

Android中SQLiteCompiledSql的使用,其实是很多数据库系统典型的实现。从应用启动,通过各种数据库操作,我们不知道进行了多少次的查询操作,而这些操作中又有相当一部分sql语句是相同的,这些编译后的sql编译对象其实是一样的,是可以共用共享的,其实就是缓存。SQLiteCompiledSql就是这样的一个需要共享的享元对象。

UML图:

其中SQLiteCompiledSql就是被管理享元对象,主要是内部状态sql语句:

class SQLiteCompiledSql {private String mSqlStmt = null;native_compile(sql);native_finalize();}

享元对象只是存放固定内容的实例,具体实现精华在管理享元对象的工厂中。

SqliteDatabase就是管理享元对象的工厂,它里面的mCompiledQuerie就是存放享元对象的容器。通常都是使用HashMap(HashTable的替代品,详细http://oznyang.iteye.com/blog/30690)进行储存。通过这种方式大大减少了sql编译对象的创建,提高了数据库操作的性能。

public class SQLiteDatabase{Map<String, SQLiteCompiledSql> mCompiledQueries = Maps.newHashMap();SQLiteCompiledSql getCompiledStatementForSql(String sql) {SQLiteCompiledSql compiledStatement = null;boolean cacheHit;synchronized(mCompiledQueries) {if (mMaxSqlCacheSize == 0) {return null;}cacheHit = (compiledStatement = mCompiledQueries.get(sql)) != null;}if (cacheHit) {mNumCacheHits++;} else {mNumCacheMisses++;}return compiledStatement;}private void deallocCachedSqlStatements() {synchronized (mCompiledQueries) {for (SQLiteCompiledSql compiledSql : mCompiledQueries.values()) {compiledSql.releaseSqlStatement();}mCompiledQueries.clear();}}void addToCompiledQueries(String sql, SQLiteCompiledSql compiledStatement) {//省略具体代码
}}

大体享元工厂都是这样一个结构:

HashMap:用作储存(就和String的常量池一样)

get方法:得到享元对象的引用

add方法:增加新的享元对象,用作初始化,一般使用者不会接触到。也有更灵活的享元模式使用会动态的增加HashMap没有的享元对象(设计模式是死的,人写出来的代码是活的,怎么用全凭大家)。

dealloc方法:释放所有的享元对象,Java有自己的内存回收机制,这个可选。

版权所有,转载请注明出处:

http://www.cnblogs.com/sickworm/p/4016026.html

转载于:https://www.cnblogs.com/sickworm/p/4016026.html

【设计模式】享元模式(Flyweight)相关推荐

  1. 设计模式:享元模式(Flyweight Pattern)

    1.享元模式:也叫蝇量模式,运行共享技术有效的支持大量细粒度的对象. 2.享元模式常用于系统底层开发,解决系统的性能问题.比如数据库连接池,里面都是创建好的连接对象. 3.享元模式能够解决重复对象的内 ...

  2. 享元模式 FlyWeight 结构型 设计模式(十五)

    享元模式(FlyWeight)  "享"取"共享"之意,"元"取"单元"之意. 意图 运用共享技术,有效的支持大量细粒度 ...

  3. 设计模式(十)享元模式Flyweight(结构型)

    设计模式(十)享元模式Flyweight(结构型) 说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释 ...

  4. 设计模式(18):结构型-享元模式(Flyweight)

    设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...

  5. 【设计模式自习室】享元模式 Flyweight Pattern:减少对象数量

    前言 <设计模式自习室>系列,顾名思义,本系列文章带你温习常见的设计模式.主要内容有: 该模式的介绍,包括: 引子.意图(大白话解释) 类图.时序图(理论规范) 该模式的代码示例:熟悉该模 ...

  6. java23设计模式---class10、享元模式(FlyWeight)

    文章目录 一.基本介绍 1.定义 2.优点 3.缺点 4.角色 1)抽象享元类 2)具体享元类 3)享元工厂类 4)组合享元类 5.内部状态和外部状态 二.应用情景 1.线程池 2.String 3. ...

  7. Python设计模式-享元模式

    Python设计模式-享元模式 基于Python3.5.2,代码如下 #coding:utf-8class Coffee:name = ""price = 0def __init_ ...

  8. JAVA 设计模式 享元模式

    用途 享元模式 (Flyweight) 运用共享技术有效地支持大量细粒度的对象. 享元模式是一种结构型模式. 结构 图-享元模式结构图 Flyweight : 它是所有具体享元类的超类或接口,通过这个 ...

  9. 设计模式--享元模式实现C++

    /********************************* *设计模式--享元模式实现 *C++语言 *Author:WangYong *Blog:http://www.cnblogs.co ...

  10. Unity设计模式——享元模式(附代码)

    Unity设计模式--享元模式(附源码) 享元Flyweight模式是什么 享元模式是一种结构型设计模式, 它摒弃了在每个对象中保存所有数据的方式, 通过共享多个对象所共有的相同状态, 让你能在有限的 ...

最新文章

  1. 使用Denyhost来阻止恶意连接SSH的IP
  2. 重新学.Net[四]——效率和安全
  3. Vue+Openlayers+el-radio实现切换地图显示
  4. Laravel核心解读 -- Response
  5. 产品开发管理方法工具流程 pdf_HR必备薪酬和绩效管理方法论、工具、案例
  6. DZY Loves Graph
  7. mem考试能用计算机吗,东华大学计算机学院MEM难考吗
  8. 3-QT程序运行时报错E:\SogouInput\6.7.0.0329\程序异常终止,该怎么解决?
  9. 【转】机器学习入门——浅谈神经网络
  10. axios http错误码处理
  11. 计算机系统盘怎么扩充,Win7如何给C盘扩容 Win7系统电脑C盘扩容的办法
  12. iOS 音乐播放器demo讲解
  13. SQLite这么娇小可爱,不多了解点都不行啊
  14. 机器人的弊议论文_机器人的利弊议论文
  15. ADP的人力资源外包方法论
  16. “向美好女人致敬”粉红丝带主题活动,谈水果养生之道
  17. matplotlib之pyplot模块——获取或设置坐标轴刻度及标签(xticks、yticks)
  18. win10无法更新计算机的启动配置,电脑升级win10后一开机关机总是显示正在配置更新请不要关闭您的计算机...
  19. 【双节快乐】十万人都在疯转的国旗中秋专属头像
  20. 定义一个学生类Student,包含三个属性姓名、年龄、性别, 创建三个学生对象存入ArrayList集合中。 A:使用迭代器遍历集合。 B:求出年龄最大的学生,然后将该对象的姓名变为:小猪佩奇。

热门文章

  1. URLClassLoader加载class到当前线程类加载器【zt】
  2. 106 网络编程实战之基于socketserver实现多用户FTP服务器
  3. 06 Python爬虫之Re(正则表达式)库
  4. 如何在Linux启动jar 包
  5. HomeBrew太慢,如何替换默认HomeBrew源,使用阿里云的源
  6. 团队作业4——第一次项目冲刺 FiRsT DaY
  7. BatchPreparedStatementSetter,用法
  8. UNIX高级环境编程(11)进程控制(Process Control)- 进程快照,用户标识符,进程调度...
  9. 远程登录 - telnet、mstsc等工具的使用及遇到的问题
  10. java static 执行顺序