来源于B站极客架构师老吴大佬
属于结构型模式
定义
Use sharing to support largenumbers of fine-grained objects efficiently.
—Gof《Design Patterns: Elements of Reusable Object-Oriented Software》
运用共享技术,有效地支持大量细粒度的对象。 ——Gof《设计模式:可复用面向对象软件的基础》
fly weight
细粒度对象
我们先看细粒度对象,它的关键点在于细,细,往往意味着量大(虽然不是绝对的)。如果一个系统中,某个对象的量级很多,往往说明这个对象,描述的是比较细节的信息。因为量大,占用的系统资源就比较多。容易形成系统瓶颈,所以需要考虑如何降低系统资源开销,提高使用效率。
系统资源占用大,在面向对象的编程中,可以从“内存”和“cpu”两个角度看。
从内存角度看,如果某个类,在JVM中,要生成大量的对象,这些对象又包含了不少重复的属性就会造成内存的浪费比较大。
从CPU角度,如果某个类,在JVM中,要不断生成大量短生命周期的对象,也就是这些对象创建后,只使用一小段时间,就需要被销毁,同一时刻,堆里面存在的对象量级可能并不大。但是因为有大量的对象要不断的创建和销毁,对CPU等系统资源占用是非常高的。因为,在JVM中,创建一个对象,属于重量级操作,耗费的系统资源比较大,这也是线程池,数据库连接池比较受欢迎的原因。
而节省系统资源的一个途径,就是看这些大量存在的细粒度对象,是否可以分离出可以共享的元对象。如果可以,通过下面要说的共享技术,就可以大大降低细粒度对象的资源占用情况。
共享技术
在享元模式的语境下,共享的就是从细粒度对象中,抽象出来的,可以共享的元对象。如何共享?
共享对象,在面向对象中,通常使用“池”技术,也就是对象缓存池,具体用什么技术实现,可以有很多选择,轻量级的,可以使用集合框架,List,Set,Map这些都可以,重量级的可以选择开源的,或者商业的缓存池组件,或者分布式缓存服务器,如redis等,我们这里使用的是开源的guavacache缓存组件。
总结一下,享元模式,就是从细粒度对象中,分离出元对象,然后通过缓存池,实现元对象的共享,以达到节省系统资源的目的。
我的理解
享元模式就是,我们在创建大量对象时,我们可以进行抽离出相同部分,然后用工厂模式创建元对象保存起来,做到多个对象对应一个共性部分,避免内存资源的浪费。
用的时候共性部分就根据对象的某个值从工厂模式里的缓存进行拿出来,多个对象相同部分公用一个内存地址
就比如我们的手机号都有归属地的,我们如果想快速查出来一个手机的归属地,我们假设把所有的手机信息都放到内存里面。归属地肯定是有重复的,我们就可以用areacode来区分不同的归属地,做成一个元对象。
这样我们在创建手机号对象时,就把areacode进行保存,一个areacode对应一个元对象。
以前是手机信息,现在变成手机信息+归属地信息两个类来保存完整的手机信息。