0 引言

0.1 目的

       本文档给出设计模式之——Flyweight模式的简化诠释,并给出其C++实现

0.2 说明

Project

Design Pattern ExplanationBy K_Eckel

Authorization

Free Distributed but Ownership Reserved

Date

2005-04-05Cherry blossom is Beautiful

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 Computer Wuhan University

E_mail

frwei@whu.edu.cn  

2 Flyweight模式

2.1 问题

       在面向对象系统的设计何实现中,创建对象是最为常见的操作。这里面就有一个问题:如果一个应用程序使用了太多的对象,就会造成很大的存储开销。特别是对于大量轻量级(细粒度)的对象,比如在文档编辑器的设计过程中,我们如果为没有字母创建一个对象的话,系统可能会因为大量的对象而造成存储开销的浪费。例如一个字母“a”在文档中出现了100000次,而实际上我们可以让这一万个字母“a”共享一个对象,当然因为在不同的位置可能字母“a”有不同的显示效果(例如字体和大小等设置不同),在这种情况我们可以为将对象的状态分为“外部状态”和“内部状态”,将可以被共享(不会变化)的状态作为内部状态存储在对象中,而外部对象(例如上面提到的字体、大小等)我们可以在适当的时候将外部对象最为参数传递给对象(例如在显示的时候,将字体、大小等信息传递给对象)。当然可能也有不想被共享的对象(例如结构图中的UnshareConcreteFlyweight),但不在本模式的讲解范围,故在实现中不给出。


2.2 模式选择

       上面解决问题的方式被称作Flyweight模式解决上面的问题,其典型的结构图为:


2-1Flyweight 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下测试运行)。

代码片断1Flyweight.h
//Flyweight.h

#ifndef _FLYWEIGHT_H_
#define _FLYWEIGHT_H_

#include <string>
using namespace std;

class Flyweight
{
public:
 virtual ~Flyweight();

 virtual void Operation(const string& extrinsicState);

 string GetIntrinsicState();

protected:
 Flyweight(string intrinsicState);

private:
 string _intrinsicState;

};

class ConcreteFlyweight:public Flyweight
{
public:
 ConcreteFlyweight(string intrinsicState);

 ~ConcreteFlyweight();

 void Operation(const string& extrinsicState);

protected:

private:
 
};
#endif //~_FLYWEIGHT_H_

代码片断2Flyweight.cpp
//Flyweight.cpp

#include "Flyweight.h"
#include <iostream>
using namespace std;

Flyweight::Flyweight(string intrinsicState)
{
 this->_intrinsicState = intrinsicState;
}

Flyweight::~Flyweight()
{

}

void Flyweight::Operation(const string& extrinsicState)
{

}

string Flyweight::GetIntrinsicState()
{
 return this->_intrinsicState;
}

ConcreteFlyweight::ConcreteFlyweight(string intrinsicState):Flyweight(intrinsicState)
{
 cout<<"ConcreteFlyweight Build....."<<intrinsicState<<endl;

}

ConcreteFlyweight::~ConcreteFlyweight()
{

}

void ConcreteFlyweight::Operation(const string& extrinsicState)
{
 cout<<"ConcreteFlyweight:
内蕴["<<this->GetIntrinsicState()<<"] 外蕴["<<extrinsicState<<"]"<<endl;
}

代码片断3FlyweightFactory.h
//FlyweightFactory.h

#ifndef _FLYWEIGHTFACTORY_H_
#define _FLYWEIGHTFACTORY_H_

#include "Flyweight.h"
#include <string>
#include <vector>
using namespace std;

class FlyweightFactory
{
public:
 FlyweightFactory();

 ~FlyweightFactory();

 Flyweight* GetFlyweight(const string& key);

protected:

private:
 vector<Flyweight*> _fly;

};
#endif //~_FLYWEIGHTFACTORY_H_

代码片断4FlyweightFactory.cpp
//FlyweightFactory.cpp

#include "FlyweightFactory.h"
#include <iostream>
#include <string>
#include <cassert>
using namespace std;

using namespace std;

FlyweightFactory::FlyweightFactory()
{

}

FlyweightFactory::~FlyweightFactory()
{

}

Flyweight* FlyweightFactory::GetFlyweight(const string& key)
{
 vector<Flyweight*>::iterator it = _fly.begin();

 for (; it != _fly.end();it++)
 {
  //
找到了,就一起用,^_^
  if ((*it)->GetIntrinsicState() == key)
  {
   cout<<"already created by users...."<<endl;

   return *it;
  }
 }

 Flyweight* fn = new ConcreteFlyweight(key);

 _fly.push_back(fn);

 return fn;
}

代码片断5main.cpp
//main.cpp

#include "Flyweight.h"
#include "FlyweightFactory.h"
#include <iostream>
using namespace std;

int main(int argc,char* argv[])
{
 FlyweightFactory* fc = new FlyweightFactory();

 Flyweight* fw1 = fc->GetFlyweight("hello");
 
 Flyweight* fw2 = fc->GetFlyweight("world!");

 Flyweight* fw3 = fc->GetFlyweight("hello");

 return 0;
}

2.3.2 代码说明

Flyweight模式在实现过程中主要是要为共享对象提供一个存放的“仓库”(对象池),

这里是通过C++ STLVector容器,当然就牵涉到STL编程的一些问题(Iterator使用等)。另外应该注意的就是对对象“仓库”(对象池)的管理策略(查找、插入等),这里是通过直接的顺序遍历实现的,当然我们可以使用其他更加有效的索引策略,例如Hash表的管理策略,当时这些细节已经不是Flyweight模式本身要处理的了。

2.4 讨论

       我们在State模式和Strategy模式中会产生很多的对象,因此我们可以通过Flyweight模式来解决这个问题。

Posted on 2005-07-08 20:56  k_eckel's mindview  阅读(529)  评论(0编辑  收藏  举报