一 应用场景
一个文本字符串存在很多的重复字符,如果每一个字符的用一个独立的对象来保存的话会浪费大量的资源。
或者围棋游戏中,每个棋子都是白色或者黑色并且大小一样只是位置不同。如果每个棋子都用一个独立的对象存储,那么和上面一样会造成大量的浪费。
享元模式就是为解决这种问题而生。
二 定义
享元模式 Flyweight Pattern:运用共享技术有效的支持大量细粒度对象的复用。使系统使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。又称为轻量级模式。
Flyweight 抽象享元类:抽象享元类,声明具体享元类的方法。
ConcreteFlyweight 具体享元类,实现抽象享元类的规定的接口,如果有内部状态的话,必须负责为内部状态提供存储空间。
UnsharedConcreteFlyweight 非共享具体享元类:不是所有的抽象享元类的子类都需要共享,不能共享的可以定义成该类。
FlyWeightFactory 抽象工厂类:创建和管理享元对象。针对抽象享元类编程,将各种类的具体享元对象储存在一个向元池中。向元池一般是一个键值对的集合。当用户请求一个具体享元对象的时候,享元工厂就提供一个储存在享元池中已经创建的实例,如果没有则新建一个。
做到享元模式的一个关键是区分内部状态(Intrinsic State)和外部状态(Extrinsic State)。下面将对享元的内部状态和外部状态进行简单的介绍:
(1) 内部状态是存储在享元对象内部并且不会随环境改变而改变的状态,内部状态可以共享。如字符的内容,不会随外部环境的变化而变化,无论在任何环境下字符“a”始终是“a”,都不会变成“b”。
(2) 外部状态是随环境改变而改变的、不可以共享的状态。享元对象的外部状态通常由客户端保存,并在享元对象被创建之后,需要使用的时候再传入到享元对象内部。一个外部状态与另一个外部状态之间是相互独立的。如字符的颜色,可以在不同的地方有不同的颜色,例如有的“a”是红色的,有的“a”是绿色的,字符的大小也是如此,有的“a”是五号字,有的“a”是四号字。而且字符的颜色和大小是两个独立的外部状态,它们可以独立变化,相互之间没有影响,客户端可以在使用时将外部状态注入享元对象中。
我们可以将具有相同内部状态的对象存储在享元池中,享元池中的对象是可以实现共享的,需要的时候就将对象从享元池中取出,实现对象的复用。通过向取出的对象注入不同的外部状态,可以得到一系列相似的对象,而这些对象在内存中实际上只存储一份。
三 C++实现一个享元模式
哪位老师有比较好的例子可以留言让我参考一下,自己目前还写不出来,网上的很多 感觉写的都不是太好。
四 总结
优点:
1 极大的减少了内存中对象的数量,使相同或者相似的对象在内存中只有一份,节约资源提高性能。
2 外部状态比较独立,不会影响内部状态。
缺点:
1 系统变得复杂化,需要分辨出外部状态和内部状态。