(C++设计模式) ------享元模式-- 结构型模式
设计模式的学习是一个循序渐进的过程,每一个设计师都是在套用这几种设计模式来实现自己的软件构架,很多都是融合会贯通的,一个设计模式中不仅仅是用到一种,所以要灵活运用这些设计模式。理解了设计模式对设计和代码的阅读都有很大的好处!!
今天我们学习结构性模式享元(flyweight)模式;
Flyweight—每天跟MM发短信,手指都累死了,最近买了个新手机,可以把一些常用的句子存在手机里,要用的时候,直接拿出来,在前面加上MM的名字就可以发送了,再不用一个字一个字敲了。共享的句子就是Flyweight,MM的名字就是提取出来的外部特征,根据上下文情况使用。
享元模式:FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。说的再具体一些是将所有具有相同状态的对象指向同一个引用,从而解决了系统在创建大量对象时所带来的内存压力。
享元模式能做到共享的关键是区分内蕴状态和外蕴状态。
内蕴状态存储在享元内部并且可以共享,不会随环境的改变而有所不同。
外蕴状态是随环境的改变而改变的,不可以共享。外蕴状态不能影响内蕴状态,它们是相互独立的。将可以共享的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出去。
亨元对象的外蕴状态必须由客户端保存,并在亨元对象被创建之后,在需要使用的时候再传入到亨元对象内部。
注意:客户端不可以直接创建被共享的对象,而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。
使用的场合:
例子:
优点:减少对象数量,节省内存空间
缺点:维护共享对象,需要额外开销
换句话说就是:享元模式的优点在于它大幅度地降低内存中对象的数量。但是,它做到这一点所付出的代价也是很高的:享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。另外它将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。
本质:
分离与共享
代码举例:引用自:http://blog.csdn.net/roynee/article/details/4633474
以纯文本为例,每个字符CharFlyweight为共享的轻量级对象,而由这些字符构成的行则为非共享的对象RowFlyweight,而TextFlyweightFactory则管理其共享对象的对象池。当用户向该工厂请求字符时,就从对象池中取得,而当用户向该工厂请求字符串时候则通过创建非共享的RowFlyweight获取,但此种每个字符的获取仍然向TextFlyweightFactory共享对象的对象池提出请求。
【程序】
// test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "iostream" #include "string" #include <vector> using namespace std; /** * AbstractFlyweight Class[Abstract Class] */ class AbstractFlyweight { public: AbstractFlyweight(){} virtual ~AbstractFlyweight(){} /// Interface of Writing the Element of Flyweight virtual void Write()=0; }; class CharFlyweight:public AbstractFlyweight { public: /*constructor and destructor*/ CharFlyweight(char tChar) { this->_Char=tChar; } virtual ~CharFlyweight(){} /// Interface of Writing the Element of Flyweight virtual void Write() { cout<<this->_Char<<flush; return; } /// Get the Char virtual char GetChar() { return this->_Char; } private: char _Char; }; class RowFlyweight:public AbstractFlyweight { public: RowFlyweight(){} virtual ~RowFlyweight(){} /// Interface of Writing the Element of Flyweight virtual void Write() { for(vector<abstractflyweight>::iterator iter=this->_vecFlyweight.begin();iter!=this->_vecFlyweight.end();++iter) (*iter)->Write(); return; } virtual void AddFlyweight(AbstractFlyweight * flyweight) { this->_vecFlyweight.push_back(flyweight); } private: vector<abstractflyweight> _vecFlyweight; }; /** * TextFlyweightFactory: provide the CharFlyweight object */ class TextFlyweightFactory { public: /*Constructor and destructor*/ TextFlyweightFactory(){} virtual ~TextFlyweightFactory(){} /// Get the CharFlyweight Object virtual AbstractFlyweight* GetFlyweight(char _char) { vector<charflyweight>::iterator iter = this->_vecCharFlyweight.begin(); for(;iter != this->_vecCharFlyweight.end();++iter) { if((*iter)->GetChar()==_char)return *iter; } CharFlyweight *newchar=new CharFlyweight(_char);/*new character*/ this->_vecCharFlyweight.push_back(newchar); /*Record it*/ return newchar; } virtual AbstractFlyweight* GetFlyweight(string str) { RowFlyweight *row=new RowFlyweight(); for(int i=0;i < str.length();++i) row->AddFlyweight(this->GetFlyweight(str[i])); /*Get the char from VecCharFlyweight*/ return row; } /// Just be used to show the size of vector virtual int SizeVector() { return this->_vecCharFlyweight.size(); } private: /*CharFlyweight Vector*/ vector<charflyweight> _vecCharFlyweight; }; int main (int argc, char *argv[]) { /*Now There is A factory*/ TextFlyweightFactory *factoryApi=new TextFlyweightFactory(); /*Now Get CharFlyweight-shared*/ factoryApi->GetFlyweight('a')->Write(); factoryApi->GetFlyweight('a')->Write(); factoryApi->GetFlyweight('c')->Write(); cout<<"\nFactory's Size is: "<<factoryapi->SizeVector(); /*Now New a Row-unshared*/ factoryApi->GetFlyweight("hello \n")->Write(); return(0); } </factoryapi-></this->
运行结果:
virtual AbstractFlyweight* GetFlyweight(string str)
不错的相关网站:①http://www.csdn.net/article/2012-06-25/2806857
② http://blog.csdn.net/roynee/article/details/4633474