为方便读者,本文已添加至索引:html
Flyweight(享元)模式运用共享技术,能够有效地支持大量细粒度的对象。今天咱们会去参观小霍比特人们的酿酒工坊……等等,不是享元模式吗?那好吧,咱们推迟到示例一节中前往参观。设计模式
咱们在作面向对象的设计时,经常但愿能用对象来表示某个具体的事物,好比一个红富士苹果或是一辆凯迪拉克跑车。当咱们把这种思惟带到一些程序设计任务中去时,可能就会遭遇处处理存储开销和程序自己灵活性的一个平衡问题。例如,咱们在设计一个游戏,主人公走到一片苹果园,看见满满一屏幕的苹果。更高级的是,每一个苹果都能与主人公进行交互,不管是近处的(直接摘下来吃了),仍是远处的(我拿石头扔,我扔)。若是每一个苹果都用不一样的对象来表示,的确能够极大提升这个游戏的视觉效果,由于这样咱们能够给每一个苹果定制彻底不一样的外观(这属于苹果的内部因素),俗话说,世界上没有两个相同的苹果(...叶子如是,苹果应该也不差)。可是,若是苹果园里,有成千上万个苹果呢?这能形成巨大的存储开销。事实上,玩游戏的时候,咱们才不会太在乎这个苹果长什么样,除非是两个彻底不一样种类的苹果。因此,若是能只存储一个苹果的外观,渲染成千上万个(存在距离、光照等外部因素),咱们也不会以为哪里不舒服,仍是会朝那些苹果扔石头。这只被共享的苹果,便引出了咱们的Flyweight模式。先来看看它的一些要点。数组
还记得这群可爱的小霍比特人们吗?(若是不了解他们,请见AbstractFactory笔记)喜欢开Party的他们,天然得有喝不完的好酒相伴。时の魔导士早先的时候曾给他们留下过一座酿酒工坊WineFactory。这座工坊能够生产各式基酒,譬如威士忌Whiskey,朗姆酒Rum,葡萄酒Wine等等。小霍比特人们,能够根据本身的口味,添加一些果汁、牛奶、咖啡、糖等等辅料,从而调制出一杯美味的鸡尾酒Cocktail。学习
在这个魔法世界里,咱们忽略每种基酒的酿造工艺上的不一样,而假定它们的内部状态是相同的(都含有酒精),区分它们的仅仅是口感的类型不一样。所以,咱们能够将基酒视做为一类ConcreteFlyweight,基酒类BaseWine继承自Drink:spa
1 class Drink { 2 public: 3 virtual ~Drink(); 4 5 virtual void mix(Ingredient&); // can mix with other ingredients. 6 virtual void drink(); 7 protected: 8 Drink(); 9 } 10 11 class BaseWine : public Drink { 12 public: 13 BaseWine(int type); 14 15 virtual void mix(Ingredient&); 16 private: 17 int _type; 18 }
当小霍比特人拜访酿酒工坊WineFactory,想要来一杯的时候。工坊会先看看他要的这种基酒是否已经酿造好了,有的话,直接取一份给他;不然,就酿造出取之不尽的这种基酒。设计
1 #define WHISKEY 1 2 #define RUM 2 3 #define VODKA 3 4 #define GIN 4 5 // ... other definitions ... 6 #define MAX_TYPES 10 7 8 class WineFactory { 9 public: 10 WineFactory(); 11 virtual ~WineFactory(); 12 virtual BaseWine* createWine(int type); 13 14 private: 15 BaseWine* _wine[MAX_TYPES]; 16 } 17 18 // Initialize the wine pool. 19 WineFactory::WineFactory() { 20 for (int i = 0; i < MAX_TYPES; ++i) { 21 _wine[i] = 0; 22 } 23 } 24 25 // Check the pool before create wine. 26 BaseWine* WineFactory::createWine(int type) { 27 if (!_wine[type]) { 28 _wine[type] = new BaseWine(type); 29 } 30 31 return _wine[type]; 32 }
咱们看到,_wine数组包含一些指针,指向以基酒品种为索引的BaseWine,createWine方法首先会查找这个数组,若是数组中存在这种BaseWine,则能够直接返回,不然,new一个新的。这样作的一个好处是,酒的种类每每是有限且很少的,可是咱们能够却能够共享这些种类并用在不少不少场景下。这个简单例子的UML图以下:指针
Flyweight主要针对存储节约提出了解决方案,它所节约的部分主要由如下几个因素决定:code
共享的Flyweight越多,存储节约也就越多。节约量随着共享状态的增多而增大。当对象使用大量的内部及外部状态,而且外部状态是计算出来的而非存储的时候,节约量将达到最大。因此,能够用两种方法来节约存储:用共享减小内部状态的消耗,用计算时间换取对外部状态的存储。htm
在使用Flyweight模式时,咱们须要注意如下几点:对象
今天的笔记就到这里了,欢迎你们批评指正!若是以为能够的话,好文推荐一下,我会很是感谢的!