一 概念
- 享元模式,运用共享技术有效的支持大量细粒度的对象。
二 UML图
- FlyweightFactory类:一个享元工厂,用来创建并管理Flyweight对象,它主要是用来确保合理的共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。
- Flyweight类:所有具体享元的类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态。
- ConcreteFlyweight类:继承Flyweight超类或实现的接口,并为内部状态增加存储空间。
- UnsharedConcreteFlyweight类:指那些不需要共享的Flyweight子类,因为Flyweight接口共享成为可能,但它并不强制共享。
三 内部状态和外部状态
四 享元模式的应用
五 C++代码实现
#include "pch.h"
#include <iostream>
#include <string>
#include <map>
using namespace std;
//用户 客户的账号是外部状态,应该由专门的对象来处理
class User
{
public:
User(string str)
:name(str) {}
string GetName() const
{
return this->name;
}
private:
string name;
};
//网站的抽象类
class WebSite
{
public:
virtual void Use(User user) = 0;
};
//具体网站类
class ConcreteWebSite : public WebSite
{
public:
ConcreteWebSite(string webname)
{
this->name = webname;
}
void Use(User user) override
{
cout << "网站分类: " << this->name
<< " 用户: " << user.GetName() << endl;
}
private:
string name;
};
//网站工厂类
class WebSiteFactory
{
public:
~WebSiteFactory()
{
map<string, WebSite*>::iterator it;
for (it = flyweights.begin(); it != flyweights.end(); ++it)
{
delete (*it).second;
}
}
WebSite* GetWebSiteCategory(string key)
{
map<string, WebSite*>::iterator it;
//判断是否存在这个对象,如果存在,则直接返回,如果不存在
//则实例化后返回
for(it = flyweights.begin(); it != flyweights.end(); it++)
{
if ((*it).first == key)
{
return (*it).second;
}
}
WebSite* website = new ConcreteWebSite(key);
flyweights.insert(make_pair(key,website));
return website;
}
int GetWebSiteCount()
{
return flyweights.size();
}
private:
map<string, WebSite*> flyweights;
};
int main()
{
WebSiteFactory* f = new WebSiteFactory();
WebSite* fx = f->GetWebSiteCategory("产品展示");
fx->Use(User("小菜"));
WebSite* fy = f->GetWebSiteCategory("产品展示");
fy->Use(User("大鸟"));
WebSite* fz = f->GetWebSiteCategory("产品展示");
fy->Use(User("娇娇"));
WebSite* fl = f->GetWebSiteCategory("博客");
fx->Use(User("老顽童"));
WebSite* fm = f->GetWebSiteCategory("博客");
fy->Use(User("桃谷六仙"));
WebSite* fn = f->GetWebSiteCategory("博客");
fy->Use(User("南海鳄神"));
cout << "得到的网站分类总数: " << f->GetWebSiteCount() << endl;
return 0;
}