享元模式(Flyweight):讨论的通过共享技术 支持大量细粒度对象。 解决系统中出现产生大量相同对象对系统性能的影响。
如何做到Flyweight 模式?
关键是区分对象内蕴状态(Internal State)和外蕴状态(External State):
内蕴状态: 对象的内蕴状态不随环境而改变,可以共享的状态。
外蕴状态: 自然状态是随环境而改变了,状态不可以共享。
所以享元模式(Flyweight)的外蕴状态必须由客户端保存, 并在享元模式(Flyweight)创建之后, 在需要使用的时候传入享元对象的内部。并且外蕴状态不能影响内蕴状态。
由于享元模式要共享对象了, 所以应该有负责提供共享对象(即享元对象)的工厂类。
Flyweight 类图:
角色说明:
Flyweight角色(可以是抽象类,接口): 此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口。 那些需要外蕴状态(External State)的操作可以通过调用业务方法以参数据形式传入。
ConcreteFlyweight角色:实现抽象类的规定的接口。如果有内蕴状态(Internal State), 必须提供内蕴状态的存储空间。 享元的内蕴状态必须与环境无关, 从而使享元对象可以实现在内存的共享。
FlyweightFactory角色:该角色负责创建和管理享元对象。 本角色必须保证享元对象被系统正确的共享。 当客户端调用一个享元对象的时候,
FlyweightFactory会检查系统中是否有复合要示的亨元对象。 如果已经有了, FlyweightFactory提供这个享元对象。 没有, FlyweightFactory负责创建一个合适的享元对象。
由于享元模式的外蕴状态要从享元对象抽取出来, 当须要使用时外蕴状态时。可以由客户端来保存外蕴状态, 也可以传参的方式将外蕴状态传入进去。
对于将外蕴状态保存在客户端,如果多个客户端,相同的逻辑会出现在所有的客户端。不利于代码的重构。而且这样也破坏了对象的封装性。
客户端将外蕴状态以传参的方式传入, 明显会更好。至少不同相同的逻辑出现在多个客户端。
什么情况下使用享元模式:满足下面所有条件,可以考虑使用享元模式。
1. 系统有大量的对象
2. 这些对象耗费大量的内存
3. 这些对象状态中的大部分可以外部化
4. 这些对象可按内蕴状态分成很多组, 当把外蕴状态从对象中剔除时,每个组都可以仅用一个对象代替。
5. 软件系统不依赖这些对象的身份,换言之,这些对象是不可分辨的。