2018-09-21 10:07:30ios
享元模式(Flyweight),运用共享技术有效的支持大量细粒度的对象。编程
· 数据结构
FlyWeightFactory:用于建立并管理享元对象,它针对抽象享元类编程,将各类类型的具体享元对象存储在一个享元池中,享元池通常设计为一个存储“键值对”的集合(也能够是其余类型的集合),能够结合工厂模式进行设计;当用户请求一个具体享元对象时,享元工厂提供一个存储在享元池中已建立的实例或者建立一个新的实例(若是不存在的话),返回新建立的实例并将其存储在享元池中。它的做用主要是为了建立并管理共享元对象,确保合理的共享Flyweight。ide
Flyweight:全部具体享元类的公共基类,经过这个基类,Flyweight能够接收并做用于外部状态。性能
SharedConcreteFlyweight(ConcreteFlyweight):实现了抽象享元类,其实例称为享元对象,在具体享元类里为内部状态提供了存储空间,一般能够结合单例模式来设计具体享元类,为每一个享元类提供惟一的享元对象。大部分时候须要使用共享元对象来下降内存的损耗,可是并非全部状况下都须要共享元,这就是UnSharedConcreteFlyweight类存在的必要性。spa
UnSharedConcreteFlyweight:这个类是指那些不须要共享的对象,虽然经过共享模式的设计(Flyweight),使得对象的共享成为可能,可是它并不会强制共享。由于在客户端使用的时候必然会有不须要共享的对象。它的存在就是为了解决那些不须要共享对象的问题。设计
共享元模式是和工厂模式是有些类似的,区别在于一方面共享元模式提供了对象的动态加入功能,另外一方面共享元模式下客户端代码不是只能使用有共享元工厂建立的产品,它能够直接使用UnSharedConcreteFlyweight的对象。另外享元模式的根本目的是为了共享对象,减小代码实例的个数,同时也提升了代码的复用性,它在使用的时候,必然是对象之间具备某种类似性才能够,而表现出的不一样之处则在于外部状态的不一样。3d
在享元对象内部而且不会随环境的改变而改变的共享部分,能够称为是享元对象的内部状态,而随环境改变而改变的、不能够共享的状态就是外部状态了,固然享元是能够没有内部状态的,而外部状态最好由客户代码或者第三方类托管。事实上,享元模式能够避免大量很是类似类的开销。在程序设计找那个,有时须要生成大量细粒度的类实例来表示数据。若是发现这些实例除了几个参数外基本上都是相同的,有时就能大幅度的减小须要实例化的类的数量。若是能把那些参数移到类实例的外部,在方法调用时将它们(外部状态)传递进来,就能够经过共享大幅度的减小单个实例的数目。code
享元模式的优缺点对象
优势:
1.经过共享对象节约了内存资源下降了性能消耗(有些状况下,对象的数量太多,会致使运行时的资源与性能损耗)
2.享元模式的内部状态稳定不变,外部状态则随环境而改变且不会影响内部状态,而外部状态的不一样又是的享元对象得出不一样的运算的结果,这使得共享对象成为了一种可能
缺点:
1.享元模式须要维护一个记录了系统已有的全部享元的列表,这自己也须要消耗资源,在每一次使用享元使都须要进行一次查找,这下降了程序的运行效率。
2.享元模式使得系统更加的复杂,由于你须要抽离出享元的内部状态和外部状态,享元在不一样环境下的外部状态都不相同,这使得程序的逻辑复杂度提高。
适用场景:
1.在对象(相同或类似的对象)足够多的时候,而这些对象形成了很大的存储开销时应该考虑使用享元模式,还有就是对象的大多数状态能够抽离为外部状态,若是删除对象的外部状态,那么能够用相对较小的共享对象取代不少组对象,此时也能够考虑使用共享模式。
2.享元必须是被大量使用的才有使用享元模式的价值,由于,在使用享元模式的时候须要维护一个全部已经存在的享元的key-value数据结构,这自己也是须要消耗资源的。
问题模型:围棋系统,在一个围棋系统中,有黑子、白子、还有棋盘、装棋子棋盒。其中黑子181个,白子180个,总共361个棋子,在下棋的过程当中,每一个棋子都会有本身的一个坐标。棋盘总共有384格,若是你为每一个实例化一个棋子对象,那么将由384个棋子对象。这里咱们可使用享元模式。接下来分析内部和外部状态。对棋子、棋盘、棋盒,它们都有固定的颜色,这个是不会改变的,因此颜色是内部状态。标准双人模式下,棋盒只有两个,棋盘一个,因此它们没有共享的意义(可是它们相对于界面来讲,依然有个显示坐标的问题,因此外部变量对他们依然成立)。对棋子来讲,每一个对象的坐标就是外部模式,根据坐标的不一样,棋子能够显示在棋盘上不一样的位置。
1.抽象享元基类(Flyweight)
#ifndef FLYWEIGHT_H_ #define FLYWEIGHT_H_ #include <iostream> #include <string> class Flyweight { public: virtual void display(const int iX,const int iY) = 0; Flyweight() = default; virtual ~Flyweight() = default; protected: std::string m_strColor; }; #endif
2.共享类(SharedFlyweight)
#ifndef SHAREDFLYWEIGHTWHITE_H_ #define SHAREDFLYWEIGHTWHITE_H_ #include "Flyweight.h" class SharedConcreteFlyweightWhite : public Flyweight { public: void display(const int iX,const int iY) override; SharedConcreteFlyweightWhite() { m_strColor = "White"; } ~SharedConcreteFlyweightWhite() = default; }; #endif #include "SharedFlyweightWhite.h" void SharedConcreteFlyweightWhite::display(const int iX,const int iY) { std::cout << " I am a " << m_strColor << "chess pieces,my coordinate is (" << iX << "," << iY << ")." << std::endl; } #ifndef SHAREDFLYWEIGHTBLACK_H_ #define SHAREDFLYWEIGHTBLACK_H_ #include "Flyweight.h" class SharedConcreteFlyweightBlack : public Flyweight { public: void display(const int iX,const int iY) override; SharedConcreteFlyweightBlack() { m_strColor = "Black"; } ~SharedConcreteFlyweightBlack() = default; }; #endif #include "SharedFlyweightBlack.h" void SharedConcreteFlyweightBlack::display(const int iX,const int iY) { std::cout << "I am a black Chess,my coordinate is (" << iX << "," << iY << ")" << std::endl; }
3.非共享的享元类(UnsharedFlyweight)
#ifndef UNSHAREDCONCRETEFLYWEIGHTCHESSBOX_H_ #define UNSHAREDCONCRETEFLYWEIGHTCHESSBOX_H_ #include "Flyweight.h" class UnsharedConcreteFlyweightChessbox : public Flyweight { public: void display(const int iX,const int iY) override; UnsharedConcreteFlyweightChessbox() { m_strColor = "Yellow"; } ~UnsharedConcreteFlyweightChessbox() = default; }; #endif #include "UnsharedConcreteFlyweightChessBox.h" void UnsharedConcreteFlyweightChessbox::display(const int iX,const int iY) { std::cout << "I am a " << m_strColor << " chessbox,my coordinate is (" << iX << "," << iY << ")" <<std::endl; }
4.Flyweight(享元模式的核心部件)
#ifndef FLYWEIGHTFACTORY_H_ #define FLYWEIGHTFACTORY_H_ #include "Flyweight.h" #include "SharedFlyweightWhite.h" #include "SharedFlyweightBlack.h" const std::string BLACKCHESS = "Black"; const std::string WHITECHESS = "White"; #include <map> class FlyweightFactory { private: std::map<std::string,Flyweight*> m_mapFlyweight; public: Flyweight* getFlyweight(const std::string strKey); int getFlyweightCount() { return m_mapFlyweight.size(); } }; #endif #include "FlyweightFactory.h" // strKey is defined class name or surname of class Flyweight* FlyweightFactory::getFlyweight(const std::string strKey) { //if find return FlyWeight object whose key is equal,otherwise new object and insert into map if(m_mapFlyweight.end() != m_mapFlyweight.find(strKey)) return m_mapFlyweight[strKey]; if(strKey == BLACKCHESS) { auto pointer = new SharedConcreteFlyweightBlack; m_mapFlyweight[strKey] = pointer; return pointer; } else if(strKey == WHITECHESS) { auto pointer = new SharedConcreteFlyweightWhite; m_mapFlyweight[strKey] = pointer; return pointer; } else { std::cout << "The key is Error!" << std::endl; return nullptr; } }
5.Client
#include "FlyweightFactory.h" #include "UnsharedConcreteFlyweightCheckerboard.h" #include "UnsharedConcreteFlyweightChessBox.h" using namespace std; int main(int argc,char *argv[]) { FlyweightFactory objFactory; auto objBlack = objFactory.getFlyweight(BLACKCHESS); if(nullptr != objBlack) objBlack->display(3,5); auto objBlack1 = objFactory.getFlyweight(BLACKCHESS); if(nullptr != objBlack1) objBlack1->display(1,4); std::cout << "count "<< objFactory.getFlyweightCount() << std::endl; auto objWhite = objFactory.getFlyweight(WHITECHESS); if(nullptr != objWhite) objWhite->display(9,9); std::cout << "count:" << objFactory.getFlyweightCount() << std::endl; auto objWhite1 = objFactory.getFlyweight(WHITECHESS); if(nullptr != objWhite1) objWhite1->display(8,8); std::cout << "count: "<< objFactory.getFlyweightCount() << std::endl; UnsharedConcreteFlyweightChessbox unshChessbox; unshChessbox.display(1,2); std::cout <<"count:" << objFactory.getFlyweightCount() << std::endl; return(1); }