设计模式之享元(FlyWeight)---对象结构型模式
1.意图
运用共享技术有效地支持大量细粒度的对象。
2.适用性
1)一个应用程序使用了大量的对象。
2)完全由于使用大量的对象,造成很大的存储开销。
3)对象的大多数状态都可变为外部状态。
4)如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
5)应用程序不依赖于对象标识。由于 FlyWeight 对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。
3.结构
1)结构图如图(F1)
2)下面的对象图说明了如何共享Flyweight。
4.参与者
*Flyweight
---描述一个接口,通过这个接口Flyweight可以接受并作用于外部状态。
*ConcreteFlyweight
---实现Flyweight接口,并为内部状态增加存储空间。ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的;即:他必须独立于ConcreteFlyweight对象的场景。
*UnsharedConcreteFlyweight
---并非所有的Flyweight子类都需要被共享,Flyweight接口使共享成为可能,但他并不强制共享。在Flyweight对象结构的某些层次,UnsharedConcreteFlyweight对象通常将ConcreteFlyweight对象作为子节点。
*FlyweightFactory
---创建并管理flyweight对象。
---确保合理的共享flyweight。当用户请求一个Flyweight时。FlyweightFactory对象提供一个已 创建的实例或者创建一个。
*Client
---维持一个对Flyweight的引用。
---计算或存储一个(多个) Flyweight的外部状态。
5.协作
1)flyweight执行时所需的状态必定是内部的或外部的。内部状态存储于 ConcreteFlyweight对象之中;外部对象则有Client 对象存储或计算。当对象那个调用flyweight对象操作时,将该状态传递给他。
2)用户不直接对ConcreteFlyweight类进行实例化,而只能从FlyweightFactory对象得到ConcreteFlyweight对象,这可保证对他们适当的共享。
6.代码示例:
/*********************************************************
*
*
*
* 下面的例子是一个文档编辑器的例子,对字符(Charact)实现共享,* 有利于节省空间存储.
*
* 对应关系:Flyweight---Glyph
* ConcreteFlyweight---Charact
* UnsharedConcreteFlyweight---Row,Column
* FlyweightFactory----GlyphFactory
*
*
*
***************************************************************/
class Window;
class GlyphContext;
class Font {
public:
Font(char*);
};
class BTree;
class Glyph {
public:
virtual ~Glyph();
virtual void Draw(Window*, GlyphContext&);
virtual void SetFont(Font*, GlyphContext&);
virtual Font* GetFont(GlyphContext&);
virtual void First(GlyphContext&);
virtual void Next(GlyphContext&);
virtual bool IsDone(GlyphContext&);
virtual Glyph* Current(GlyphContext&);
virtual void Insert(Glyph*, GlyphContext&);
virtual void Remove(GlyphContext&);
protected:
Glyph();
};
class Character : public Glyph {
public:
Character(char);
virtual void Draw(Window*, GlyphContext&);
private:
char _charcode;
};
class GlyphContext {
public:
GlyphContext();
virtual ~GlyphContext();
virtual void Next(int step = 1);
virtual void Insert(int quantity = 1);
virtual Font* GetFont();
virtual void SetFont(Font*, int span = 1);
private:
int _index;
BTree* _fonts;
};
void dummy () {
GlyphContext gc;
Font* times12 = new Font("Times-Roman-12");
Font* timesItalic12 = new Font("Times-Italic-12");
// ...
gc.SetFont(times12, 6);
gc.Insert(6);
gc.SetFont(timesItalic12, 6);
}
class Row {
};
class Column {
};
const int NCHARCODES = 128;
class GlyphFactory {
public:
GlyphFactory();
virtual ~GlyphFactory();
virtual Character* CreateCharacter(char);
virtual Row* CreateRow();
virtual Column* CreateColumn();
// ...
private:
Character* _character[NCHARCODES];
};
GlyphFactory::GlyphFactory () {
for (int i = 0; i < NCHARCODES; ++i) {
_character[i] = 0;
}
}
Character* GlyphFactory::CreateCharacter (char c) {
if (!_character[c]) {
_character[c] = new Character(c);
}
return _character[c];
}
、
Row* GlyphFactory::CreateRow () {
return new Row;
}
Column* GlyphFactory::CreateColumn () {
return new Column;
}
//附: 想起来挺简单的,可这个模式要实现真不会.