1. 享元模式的概念
享元模式, 运用共享技术可以有效的支持大量细粒度的对象。
利用享元工厂, 用来创建并且管理 享元对象。
我们把享元对象内部并且不会随着环境改变而改变的部分, 称为是享元的内部对象, 而把随着环境改变而改变的, 不可以被共享的状态, 称为是外部对象。
享元模式, 可以避免大量相似的类的开销。在程序设计过程中, 有时候需要生成大量细粒度的类实例来表示数据。 如果可以发现这些实例除了几个参数之外基本都是相同的话, 就可以大幅度的减少单个实例的数目。
简单的来说, 本来我们需要为每个用户, 每类网站, 都构建一个类的实例。
但是, 利用享元模式, 我们提取相同部分, 进行改造, 借助享元工厂, 可以避免创建大量的类实例
通常, 如果一个应用程序使用了大量的对象, 而大量的这些对象造成了很大的存储开销的时候, 我们就需要考虑享元模式了, 另外如果对象的大多数对象可以使用外部状态表示, 如果删除这些对象的外部对象, 那么就可以使用相对较少的共享对象取代很多组对象, 这时候也是需要考虑享元模式的。
享元模式需要维护一个记录了系统已有的所有享元的列表, 本身也是需要耗费资源的, 还有他会使得系统变得复杂。
2. UML
3. 运行效果图
4. code
user.h
#ifndef _USER_H_
#define _USER_H_#include <string>
using std::string;class User{
public:string Name() const { return name; }User(string name) :name(name){}private:string name;
};#endif // _USER_H_
website
#ifndef _WEBSITE_H_
#define _WEBSITE_H_#include "User.h"class WebSite{
public:virtual void Use(User * user) = 0;
};#endif
concreteWebsite.h
#ifndef _CONCRETEWEBSITE_H_
#define _CONCRETEWEBSITE_H_#include "WebSite.h"
#include <string>
#include <iostream>using std::cout;
using std::endl;
using std::string;class ConcreteWebsite : public WebSite{
public:ConcreteWebsite(string name) : name(name){}void Use(User * user){cout << "网站分类:\t" << name << " 用户:\t" << user->Name() << endl;}private:string name;
};#endif // _CONCRETEWEBSITE_H_
websiteFactory.h
#ifndef _WEBSITEFACTORY_H_
#define _WEBSITEFACTORY_H_#include "ConcreteWebSite.h"
#include <string>
#include <memory>
#include <unordered_map>using std::string;
using std::unordered_map;
using std::shared_ptr;
using std::make_pair;class WebsiteFactory{
public:shared_ptr<WebSite> GetWebSiteCategory(string key){if (flyweights.find(key) == flyweights.end())flyweights.insert(make_pair(key, shared_ptr<WebSite>(new ConcreteWebsite(key))));return flyweights[key];}int GetWebSiteCount(){ return flyweights.size(); }private:unordered_map<string, shared_ptr<WebSite>> flyweights;
};#endif // _WEBSITEFACTORY_H_
main.cpp
#include <string>
#include <memory>using namespace std;int main(){shared_ptr<WebsiteFactory> f(new WebsiteFactory);shared_ptr<WebSite> fx = f->GetWebSiteCategory("产品展示");fx->Use(shared_ptr<User>(new User("大鸟")).get());shared_ptr<WebSite> fy = f->GetWebSiteCategory("产品展示");fy->Use(shared_ptr<User>(new User("小菜")).get());shared_ptr<WebSite> fz = f->GetWebSiteCategory("产品展示");fz->Use(shared_ptr<User>(new User("娇娇")).get());system("pause");return 0;
}