享原模式的官方定义:
运用共享技术有效地支持大量细粒度的对象。
大白话讲:
一个类它可能生成好多对象,但这些对象根据属性值的不同一共分成N类,每种类型中属性值都是一样的。在这种情况下,如果创建好多对象,那么这些对象中很多属性值都是重复的,从而造成了大量的内存浪费。
而享元模式能够解决重复对象的内存浪费的问题。
享元模式使用一个工厂类,在工厂类中为每种类型创建一个对象,而且每种类型的对象只有一个。
当客户端需要某种类型的对象的时候,工厂将已创建好的对象给客户端。由于不创建新的对象了,所以节省了内存。
享元模式的类图:
客户端通过Factory.getFlyweight(key)来获取指定类型的Flyweight对象。
但这样有一个问题,有时候指定类型的对象中的某几个属性值可能不同,如果通过工厂获得的对象,由于他们都是统一个对象,因此他们的属性值都是完全一样的,这时就需要将属性值不一样的属性存在外部对象中,外部对象作为参数传递给Flyweight的函数,这些函数在执行过程中当遇到特殊属性的时候就会调用外部对象中的值。类图如下:
这里的User就是用于存储特殊值的外部类,在Flyweight类中需要用到属性特殊值的函数都需要将含有特殊属性值的外部类对象作为参数传递进来。
外部状态与内部状态:
在享元对象中,不会随环境变化而变化的共享属性称为享元的内部状态;
而随着环境变化而变化的,不可以共享的状态就是享元的外部状态。
何时使用?
享元模式可以避免大量非常相似的对象的开销。
在程序设计中,如果发现需要大量细粒度的类对象来表示数据,而且这些类除了几个参数不同以外,其他的属性都是相同的,这时候就可以使用享元模式。类中相同的属性可以通过工厂类来共享,这些属性就是享元类的内部状态;而那些会变化的属性放在新建的外部对象中,作为参数传递给享元类的函数。
享元模式的优点:
享元模式通过共享对象的方式,把所有对象的公共属性存放在同一个对象中,不同的属性存放在外部类中,从而起到了节省存储空间的作用。