文章目录
前言
创建对象的过程在面向对象系统的设计中是最经常用到的设计方法。但是,如果在设计过程中创建了太多的对象,会造成存储空间的巨大开销或者浪费。特别是对于大量轻量级(细粒度)的对象,比如在文档编辑器的设计过程中,我们如果为没有字母创建一个对象的话,系统可能会因为大量的对象而造成存储开销的浪费。例如一个字母“a”在文档中出现了100000 次,而实际上我们可以让这一万个字母“a”共享一个对象,当然因为在不同的位置可能字母“a”有不同的显示效果(例如字体和大小等设置不同),在这种情况我们可以为将对象的状态分为“外部状态”和“内部状态”,将可以被共享(不会变化)的状态作为内部状态存储在对象中,而外部对象(例如上面提到的字体、大小等)我们可以在适当的时候将外部对象最为参数传递给对象(例如在显示的时候,将字体、大小等信息传递给对象)。
一、享元模式( Flyweight 模式)
Flyweight 模式中存在类似 Factory 模式的对象构造工厂FlyweightFactory,当客户(Client)需要一个对象时候就会向 FlyweightFactory 发出请求对象的消息 GetFlyweight()消息,FlyweightFactory 拥有一个管理、存储对象的“仓库”(或者叫对象池,这里采用map实现,方便查找),GetFlyweight()消息会遍历对象池中的对象,如果已经存在则直接返回给 Client,否则创建一个新的对象返回给 Client。UML图如下:
二、具体源码
1.FlyWeight.h
代码如下(示例):
#ifndef _FLYWEIGHT_H_
#define _FLYWEIGHT_H_
#include <iostream>
#include <string>
class Flyweight
{
public:
virtual ~Flyweight();
virtual void Operation(const std::string& extrinsicState);
std::string GetIntrinsicState();
protected:
Flyweight(std::string intrinsicState);
private:
std::string _intrinsicState;
};
class ConcreteFlyweight :public Flyweight
{
public:
ConcreteFlyweight(std::string intrinsicState);
~ConcreteFlyweight();
//子类中实现接口,如字体“a”设置大小、颜色等
void Operation(const std::string& extrinsicState);
protected:
private:
};
#endif //_FLYWEIGHT_H_
2.FlyWeight.cpp
代码如下(示例):
#include "Flyweight.h"
Flyweight::Flyweight(std::string intrinsicState)
{
this->_intrinsicState = intrinsicState;
}
Flyweight::~Flyweight()
{
}
void Flyweight::Operation(const std::string& extrinsicState)
{
this->_intrinsicState += extrinsicState;
}
std::string Flyweight::GetIntrinsicState()
{
return this->_intrinsicState;
}
ConcreteFlyweight::ConcreteFlyweight(std::string intrinsicState) :Flyweight(intrinsicState)
{
std::cout << "ConcreteFlyweight Build....." << intrinsicState << std::endl;
}
ConcreteFlyweight::~ConcreteFlyweight()
{
}
void ConcreteFlyweight::Operation(const std::string& extrinsicState)
{
std::cout << "ConcreteFlyweight:内蕴[" << this->GetIntrinsicState() << "] 外 蕴[" << extrinsicState << "]" << std::endl;
}
3.FlyWeightFactory.h
代码如下(示例):
#pragma once
#ifndef _FLYWEIGHTFACTORY_H_
#define _FLYWEIGHTFACTORY_H_
#include "Flyweight.h"
#include <map>
#include <cassert>
class FlyweightFactory
{
public:
FlyweightFactory();
~FlyweightFactory();
Flyweight * GetFlyweight(const std::string& key);
protected:
private:
//存储内部对象,采用map方便查找
std::map<std::string,Flyweight*> _fly;
};
#endif //_FLYWEIGHTFACTORY_H_
4.FlyWeightFactory.cpp
代码如下(示例):
#include "FlyweightFactory.h"
FlyweightFactory::FlyweightFactory()
{
}
FlyweightFactory::~FlyweightFactory()
{
//注意析构函数需要将申请的内存进行销毁
for (auto itor : _fly)
{
delete _fly[itor.first];
_fly[itor.first] = nullptr;
}
}
Flyweight* FlyweightFactory::GetFlyweight(const std::string& key)
{
//若存在,在返回对象
if (this->_fly.count(key) != 0)
return this->_fly[key];
//不存在时,常见新对象并返回
else
{
Flyweight * fn = new ConcreteFlyweight(key);
_fly[key]=fn;
return fn;
}
}
5.main.cpp
代码如下(示例):
#include "Flyweight.h"
#include "FlyweightFactory.h"
int main(int argc, char* argv[])
{
FlyweightFactory* fc = new FlyweightFactory();
Flyweight* fw1 = fc->GetFlyweight("hello");
fw1->Operation("world!");
Flyweight* fw2 = fc->GetFlyweight("Good morning!");
Flyweight* fw3 = fc->GetFlyweight("hello");
fw3->Operation("China!");
return 0;
}
三、运行结果
Flyweight 模式运行结果如下:
总结
Flyweight 模式主要用于减少创建对象的数量,以减少内存占用和提高性能,属于结构型模式。好处是:减少了对象数量,使得相同对象或相似对象在内存中只保存一份,从而改善应用所需的对象结构的方式,同时内部状态与外部状态相对独立,而且不会影响其相互影响,从而使得内部对象可以在不同的环境中被共享。但是,它也会使得系统更加复杂,为了使对象可以共享,需要将一些状态外部化,这样使得程序的逻辑复杂化。
本文参考《设计模式精解-GoF 23 种设计模式解析附 C++实现源码》,对内容进行整理,方便大家学习。如想学习详细内容,请参考此书。