概述
一个软件系统在运行时产生的对象数量太多,将导致运行代价过高,带来系统性能下降等问题。
想想我们编辑文档用的word,文档里文字很多都是重复的,我们不可能为每一个出现的汉字都创建独立的空间,这样代价太大,那么我们如何去避免系统中出现大量相同或相似的对象,同时又不影响客户端程序通过面向对象的方式对这些对象进行操作?
享元模式正为解决这一类问题而诞生。享元模式通过共享技术实现相同或相似对象的重用,在逻辑上每一个出现的字符都有一个对象与之对应,然而在物理上它们却共享同一个享元对象,这个对象可以出现在一个字符串的不同地方,相同的字符对象都指向同一个实例,在享元模式中,存储这些共享实例对象的地方称为享元池(Flyweight Pool)。我们可以针对每一个不同的字符创建一个享元对象,将其放在享元池中,需要时再从享元池取出。
实现策略
作用:运用共享技术有效地支持大量细粒度的对象。
内部状态intrinsic和外部状态extrinsic:
1)Flyweight模式中,最重要的是将对象分解成intrinsic和extrinsic两部分。2)内部状态:在享元对象内部并且不会随环境改变而改变的共享部分,可以称为是享元对象的内部状态
3)外部状态:而随环境改变而改变的,取决于应用环境,或是实时数据,这些不可以共享的东西就是外部状态了。
4)内部状态和外部状态之间的区别:
在Flyweight模式应用中,通常修改的是外部状态属性,而内部状态属性一般都是用于参考或计算时引用。
Flyweight执行时所需的状态必定是内部的或外部的。内部状态存储于ConcreteFlyweight对象之中;而外部状态则由Client对象存储或计算。当用户调用Flyweight对象的操作时,将该状态传递给它。
以文字处理软件为例:
内部状态存储于flyweight中,它包含了独立于flyweight场景的信息,这些信息使得flyweight可以被共享。如字符代码,字符大小……
外部状态取决于flyweight场景,并根据场景而变化,因此不可共享。用户对象负责在必要的时候将外部状态传递给flyweight,如字符位置,字符颜色……
组成
①Flyweight:
享元类的基类,定义一个接口,通过这个接口Flyweight可以接受并作用于外部状态。
②ConcreteFlyweight:
实现Flyweight接口, 并为内部状态( 如果有的话) 增加存储空间。ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的(intrinsic);即,它必须独立于ConcreteFlyweight对象的场景。
③UnsharedConcreteFlyweight:
并非所有的Flyweight子类都需要被共享。Flyweight接口使共享成为可能,但它并不强制共享。在Flyweight对象结构的某些层次,④UnsharedConcreteFlyweight对象通常将ConcreteFlyweight对象作为子节点。
⑤FlyweightFactory:
1) 创建并管理Flyweight对象。2)确保合理地共享Flyweight。当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)
⑥Client
1)维持一个对Flyweight的引用。2)计算或存储一个(多个)Flyweight的外部状态。
UML
示例代码
// Flyweight.h
- // Flyweight.h
- #ifndef _FLYWEIGHT_H_
- #define _FLYWEIGHT_H_
- #include <string>
- #include <vector>
- using namespace std;
- //基类,定义操作接口Operation
- class Flyweight
- {
- public:
- //操作外部状态extrinsicState
- virtual void Operation(const string& extrinsicState) = 0;
- string GetIntrinsicState( );
- virtual ~Flyweight( );
- protected:
- Flyweight(string intrinsicState);
- private:
- // 内部状态,也可以放在ConcreteFlyweight中
- string _intrinsicState;
- };
- /*
- ConcreteFlyweight:实现Flyweight接口, 并为内部状态( 如果有的话) 增加存储空间。
- ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的(intrinsic);
- 即,它必须独立于ConcreteFlyweight对象的场景。
- */
- class ConcreteFlyweight : public Flyweight
- {
- public:
- //实现接口函数
- virtual void Operation(const string& extrinsicState);
- ConcreteFlyweight(string intrinsicState);
- ~ConcreteFlyweight();
- };
- /*
- UnsharedConcreteFlyweight:并非所有的Flyweight子类都需要被共享。
- Flyweight接口使共享成为可能,但它并不强制共享。
- 在Flyweight对象结构的某些层次,
- UnsharedConcreteFlyweight对象通常将ConcreteFlyweight对象作为子节点。
- */
- class UnsharedConcreteFlyweight:public Flyweight
- {
- public:
- virtual void Operation(const string& extrinsicState);
- UnsharedConcreteFlyweight(string intrinsicState);
- ~UnsharedConcreteFlyweight();
- };
- class FlyweightFactory
- {
- public:
- FlyweightFactory();
- ~FlyweightFactory();
- //获得一个请求的Flyweight对象
- Flyweight* GetFlyweight(string key);
- //获取容器中存储的对象数量
- void GetFlyweightCount();
- protected:
- private:
- //保存内部状态对象的容器
- vector<Flyweight*> m_vecFly;
- };
- #endif
// Flyweight.cpp
- // Flyweight.cpp
- #include "Flyweight.h"
- #include <iostream>
- using namespace std;
- Flyweight::Flyweight(string intrinsicState)
- {
- this->_intrinsicState = intrinsicState;
- }
- Flyweight::~Flyweight()
- {}
- string Flyweight::GetIntrinsicState()
- {
- return this->_intrinsicState;
- }
- ConcreteFlyweight::ConcreteFlyweight(string intrinsicState):Flyweight(intrinsicState)
- {
- }
- ConcreteFlyweight::~ConcreteFlyweight()
- {
- }
- void ConcreteFlyweight::Operation(const string& extrinsicState)
- {
- cout << this->GetIntrinsicState() << endl;
- cout << extrinsicState << endl;
- }
- UnsharedConcreteFlyweight::UnsharedConcreteFlyweight(string intrinsicState):Flyweight(intrinsicState)
- {
- }
- UnsharedConcreteFlyweight::~UnsharedConcreteFlyweight()
- {
- }
- void UnsharedConcreteFlyweight::Operation(const string& extrinsicState)
- {
- cout << "extrinsicState" << endl;
- }
- FlyweightFactory::FlyweightFactory()
- {}
- FlyweightFactory::~FlyweightFactory()
- {}
- //若该对象已存在,直接返回,否则新建一个对象,存入容器中,再返回
- Flyweight* FlyweightFactory::GetFlyweight(string key)
- {
- vector<Flyweight*>::iterator iter = this->m_vecFly.begin();
- for(;iter!= this->m_vecFly.end();iter++)
- {
- if((*iter)->GetIntrinsicState() == key)
- {
- return *iter;
- }
- }
- Flyweight* fly = new ConcreteFlyweight(key);
- this->m_vecFly.push_back(fly);
- return fly;
- }
- void FlyweightFactory::GetFlyweightCount()
- {
- cout << this->m_vecFly.size() << endl;
- }
- #include "Flyweight.h"
- #include <iostream>
- #include <string>
- using namespace std;
- int main()
- {
- //外部状态extrinsicState
- string extrinsicState = "ext";
- //工厂对象,工厂对象
- FlyweightFactory* fc = new FlyweightFactory();
- //向工厂申请一个Flyweight对象,且该对象的内部状态值为“hello”
- Flyweight* fly = fc->GetFlyweight("hello");
- Flyweight* fly1 = fc->GetFlyweight("hello");
- //应用外部状态
- fly->Operation(extrinsicState);
- fc->GetFlyweightCount();
- return 0;
- }
Makefile
- CC = gcc
- CXX = g++
- OBJECT = Flyweight.o main.o
- TARGET = Flyweight.exe
- INC = -I./
- $(TARGET) : $(OBJECT)
- $(CXX) $(OBJECT) -o $(TARGET)
- %.o : %.cpp
- $(CXX) -c $< -o $@ $(INC)
- .PHONY : clean
- clean :
- del $(OBJECT) $(TARGET)
- rm -rf $(OBJECT) $(TARGET)
参考:
另外一个围棋的例子:
转载:http://blog.csdn.net/gatieme/article/details/24925741