0 引言
0.1 目的
本文档给出设计模式之——Flyweight模式的简化诠释,并给出其C++实现。
0.2 说明
Project |
Design Pattern Explanation(By K_Eckel) |
Authorization |
Free Distributed but Ownership Reserved |
Date |
|
Test Bed |
MS Visual C++ 6.0 |
0.3 参考
在本文档的写作中,参考了以下的资源,在此列出表示感谢:
u 书籍
[GoF 2000]:GoF,Design Patterns-Elements of Reusable Object-Oriented Software
Addison-Wesley 2000/9.
[Martine 2003]:Robert C.Martine, Agile Software Development Principles, Patterns, and Practices, Pearson Education, 2003.
0.4 联系作者
Author |
K_Eckel |
State |
Candidate for Master’s Degree School of |
E_mail |
2 Flyweight模式
2.1 问题
在面向对象系统的设计何实现中,创建对象是最为常见的操作。这里面就有一个问题:如果一个应用程序使用了太多的对象,就会造成很大的存储开销。特别是对于大量轻量级(细粒度)的对象,比如在文档编辑器的设计过程中,我们如果为没有字母创建一个对象的话,系统可能会因为大量的对象而造成存储开销的浪费。例如一个字母“a”在文档中出现了100000次,而实际上我们可以让这一万个字母“a”共享一个对象,当然因为在不同的位置可能字母“a”有不同的显示效果(例如字体和大小等设置不同),在这种情况我们可以为将对象的状态分为“外部状态”和“内部状态”,将可以被共享(不会变化)的状态作为内部状态存储在对象中,而外部对象(例如上面提到的字体、大小等)我们可以在适当的时候将外部对象最为参数传递给对象(例如在显示的时候,将字体、大小等信息传递给对象)。当然可能也有不想被共享的对象(例如结构图中的UnshareConcreteFlyweight),但不在本模式的讲解范围,故在实现中不给出。
2.2 模式选择
上面解决问题的方式被称作Flyweight模式解决上面的问题,其典型的结构图为:
图2-1:Flyweight Pattern结构图
可以从图2-1中看出,Flyweight模式中有一个类似Factory模式的对象构造工厂FlyweightFactory,当客户程序员(Client)需要一个对象时候就会向FlyweightFactory发出请求对象的消息GetFlyweight()消息,FlyweightFactory拥有一个管理、存储对象的“仓库”(或者叫对象池,vector实现),GetFlyweight()消息会遍历对象池中的对象,如果已经存在则直接返回给Client,否则创建一个新的对象返回给Client。
2.3 实现
2.3.1 完整代码示例(code)
Flyweight模式完整的实现代码(所有代码采用C++实现,并在VC 6.0下测试运行)。
代码片断1:Flyweight.h #ifndef _FLYWEIGHT_H_ #include <string> class Flyweight virtual void Operation(const string& extrinsicState); string GetIntrinsicState(); protected: private: }; class ConcreteFlyweight:public Flyweight ~ConcreteFlyweight(); void Operation(const string& extrinsicState); protected: private: |
代码片断2:Flyweight.cpp #include "Flyweight.h" Flyweight::Flyweight(string intrinsicState) Flyweight::~Flyweight() } void Flyweight::Operation(const string& extrinsicState) } string Flyweight::GetIntrinsicState() ConcreteFlyweight::ConcreteFlyweight(string intrinsicState):Flyweight(intrinsicState) } ConcreteFlyweight::~ConcreteFlyweight() } void ConcreteFlyweight::Operation(const string& extrinsicState) |
代码片断3:FlyweightFactory.h #ifndef _FLYWEIGHTFACTORY_H_ #include "Flyweight.h" class FlyweightFactory ~FlyweightFactory(); Flyweight* GetFlyweight(const string& key); protected: private: }; |
代码片断4:FlyweightFactory.cpp #include "FlyweightFactory.h" using namespace std; FlyweightFactory::FlyweightFactory() } FlyweightFactory::~FlyweightFactory() } Flyweight* FlyweightFactory::GetFlyweight(const string& key) for (; it != _fly.end();it++) return *it; Flyweight* fn = new ConcreteFlyweight(key); _fly.push_back(fn); return fn; |
代码片断5:main.cpp #include "Flyweight.h" int main(int argc,char* argv[]) Flyweight* fw1 = fc->GetFlyweight("hello"); Flyweight* fw3 = fc->GetFlyweight("hello"); return 0; |
2.3.2 代码说明
Flyweight模式在实现过程中主要是要为共享对象提供一个存放的“仓库”(对象池),
这里是通过C++ STL中Vector容器,当然就牵涉到STL编程的一些问题(Iterator使用等)。另外应该注意的就是对对象“仓库”(对象池)的管理策略(查找、插入等),这里是通过直接的顺序遍历实现的,当然我们可以使用其他更加有效的索引策略,例如Hash表的管理策略,当时这些细节已经不是Flyweight模式本身要处理的了。
2.4 讨论
我们在State模式和Strategy模式中会产生很多的对象,因此我们可以通过Flyweight模式来解决这个问题。