标签:
1. 享元模式(Flyweight Pattern)的定义
(1)运用共享技术高效地支持大量细粒度的对象
①对象内部状态:数据不变且重复出现,这部分不会随环境变化而改变,是可以共享的。
②对象外部状态:数据是变化的,会随环境变化而改变,是不可以共享的。
③所谓的享元,就是把内部状态的数据分离出来共享,通过共享享元对象,可以减少对内存的占用。把外部状态分离出来,放到外部,让应用程序在使用的时候进行维护,并在需要的时候传递给享元对象使用。
④享元模式真正缓存和共享的是享元的内部状态,而外部状态是不被缓存共享的。同时内部状态和外部状态是独立的,外部状态的变化不会影响到内部状态。
(2)享元模式的结构和说明
①Flyweight:接口或抽象类,通过这个接口Flyweight可以接受并作用于外部状态。通过这个接口传入外部的状态,在享元对象的方法处理中可能会使用这些外部的数据。
②ConcreteFlyweight:具体的享元实现对象,必须是可共享的,为内部状态提供成员变量进行存储。(真正要被共享的对象)
③UnsharedConcreteFlyweight:非共享的享元实现对象,并不是所有的Flyweight实现对象都需要共享。非共享的享元实现对象通常是对共享享元对象的组合对象,这种对象虽然不需要加入到享元工厂中去共享,但也继承自Flyweight,其好处是可以统一接口。注意,本例中的UnsharedConcreteFlyweight是从Flyweight继承而来,有时也可以不用继承自Flyweight。(该类的作用:提供外部状态存储)
④FlyweightFactory:为控制内部状态的共享,并且让外部能简单地使用共享数据,提供一个工厂来管理享元,把它称为享元工厂。其作用主要用来创建并管理共享的享元对象,享元池一般设计成键值对。这里也对外提供访问共享享元的接口。
⑤Client:享元客户端,主要的工作是维持一个对Flyweight的引用,计算或存储享元对象的外部状态。当然这里可以访问共享和不共享的Flyweight对象。
(3)思考享元模式
①享元模式的本质:分离与共享。享元模式的关键在于分离变与不变,把不变部分作为享元对象的内部状态,而变化部分则作为外部状态,由外部来维护.这样享元对象就能够被共享,从而减少对象的数量,并节省大量的内存空间。
②享元模式的变与不变:为什么在一个地方要预留接口,一个常见的原因是这里存在变化,可能在今后需要扩展或改变己有的实现,而预留接口作为“可插入性的保证”
③享元对象:又有共享(ConcreteFlyweight)与不共享(UnsharedConcreteFlyweight)之分。不共享一般出现在和组合模式合用的情况,通常共享是叶子对象,一般不共享的部分是由共享部分组合而成,由于所有细粒度的叶子对象己经缓存了,那么缓存组合对象就没有什么意义。(如权限管理中某安全实体的“查看”和“修改”是可共享的,如果将“查看”和“修改”组合成“操作”权限的话,则“操作”权限是不用缓存(共享)的,因为己经在细粒度上进行了缓存)。(见后面的例子)
【编程实验】围棋软件设计
①内部状态:每个围棋那么多的棋子,可设置为享元对象,有如下属性颜色、大小、形状。
②外部状态:棋子在棋盘中的位置。这是不可共享的。
//结构型模式:享元模式 //场景:围棋软件设计。 //内部状态——围棋棋子数量多,但分只为两类:白棋和黑棋。 // 有颜色、大小、形态等属性,是可共享的对象。 //外部状态——棋子在棋盘中的位置。 #include <iostream> #include <string> #include <map> using namespace std; //************************************享元类************************** class Coordinate; //前向声明 //享元抽象类 class ChessFlyweight { public: virtual string& getColor() = 0; virtual void setColor(string color) = 0; //显示棋子在棋盘中的位置 //可以通过这个接口,将外部状态传入享元对象中 virtual void display(Coordinate& c) = 0; }; //非享元对象:UnsharedConcreteFlyweight(外部状态) class Coordinate { int x,y; public: Coordinate(int x, int y){this->x = x;this->y = y;} int getX(){return x;} void setX(int x){this->x = x;} int getY(){return y;} void setY(int x){this->y = y;} }; //享元对象:ConcreteFlyweight(内部状态) class ConcreteChess : public ChessFlyweight { private: string color; public: ConcreteChess(string color){this->color = color;} string& getColor() {return color;} void setColor(string color){this->color = color;} void display(Coordinate& c) { cout << "Chess‘s Color: " << color << endl; cout << "Position: x = " << c.getX() << " y = " << c.getY() << endl; } }; //************************************享元工厂类************************** class ChessFlyweightFactory { private: static map<string,ChessFlyweight*> chessMap; public: static ChessFlyweight* getChess(string color) { ChessFlyweight* ret = chessMap[color]; if(ret == NULL) { ret = new ConcreteChess(color); chessMap[color] = ret; } return ret; } static void clear() { map<string, ChessFlyweight*>::iterator iter = chessMap.begin(); while(iter != chessMap.end()) { delete iter->second; cout <<iter->second << endl; ++iter; } chessMap.clear(); } }; map<string,ChessFlyweight*> ChessFlyweightFactory::chessMap; int main() { ChessFlyweight* chess1 = ChessFlyweightFactory::getChess("black"); ChessFlyweight* chess2 = ChessFlyweightFactory::getChess("black"); ChessFlyweight* chess3 = ChessFlyweightFactory::getChess("white"); cout << "chess1 = " << chess1 << endl; cout << "chess2 = " << chess2 << endl; cout << "chess3 = " << chess3 << endl; //增加外部状态的处理 cout << "extrinsic state: " << endl; Coordinate c1(10, 10); Coordinate c2(20, 20); Coordinate c3(30, 30); chess1->display(c1); chess2->display(c2); chess3->display(c3); //删除享元池中的对象 ChessFlyweightFactory::clear(); return 0; }
标签:
原文地址:http://www.cnblogs.com/5iedu/p/5544753.html