设计模式——享元模式

速读技术文章时,碰到一个单词:享元模式。查资料虔诚学习一下。

享元模式 Flyweight Pattern

可能这个名词不少人觉得有点陌生,但实际工作中应该见过甚至使用过。很典型的应用就是缓存、线程池和连接池等。

如果需要生成大量细粒度的类实例来表示数据,并且这些实例除了几个参数外基本都是相同的,就可以使用享元模式。如果把这些参数(指的是这是实例不同的参数)移动到类的外面,在调用方法时把他们传递进来,这样就通过共享数据,减少了单个实例的数目,我们把类实例外面的参数称之为享元对象的外部状态,把在享元模式内部定义称之为内部状态。

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

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

主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。

应用实例: 1、JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。 2、数据库的数据池。

使用场景: 1、系统有大量相似对象。 2、需要缓冲池的场景。

注意事项: 1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。 2、这些类必须有一个工厂对象加以控制。

其实不仅仅是内存,新生成对象时,特别是同时生成很多对象,也是很耗CPU等,笔者早年经历,初学Unity3D游戏开发,连发水珠/子弹(在程序中即对象集合),同时批量实例化,用完销毁/需要时再生成,很耗硬件资源(特别是CPU),手机运行卡顿明显。后经指点,使用对象池缓存对象,不再重复生产/销毁一批对象,需要对象时,从池子取出并初始化相关状态(子弹坐标等),成功解决卡顿问题。当时并没有意识到这就是享元模式。另外游戏中渲染一片森林、一批怪兽等相似物品也是享元模式典型场景。
附录RUNOOB这个例子就比较接近游戏开发。

单纯享元模式,实现也很简单,示例见附录链接,不再赘述。抽空上一份复合享元模式的代码。


附:
廖雪峰:享元
RUNOOB享元模式

多说几句:设计模式不是 Java 的专利,它同样适用于 C++、C#、JavaScript、Python 等其它面向对象的编程语言。如果把算法比作将才,设计模式就是帅才。不过,一般只有在有足够的工程实践经验的基础上才能领会、发挥设计模式的作用。所以,不建议没有足够工程实践基础的初学者抱着书籍硬啃、练,啃得快忘得快。除非你是要准备面试,不啃不行。比较好的学习方式是:在实践中学习,在学习中实践。