现在的位置: 首页 > 综合 > 正文

[设计模式笔记]二. 结构型模式–12.Flyweight模式(享元模式)(二)

2013年10月22日 ⁄ 综合 ⁄ 共 1467字 ⁄ 字号 评论关闭

场景

文档编辑器(该编辑器只能编辑24个字母和空格可以修改字体大小颜色)(位置可以动态计算).

角色

CharacterFactory 负责管理24个字符和空格CharacterFlyweight对象里面需要有一个Flyweight列表列表存储对象指针.

Flyweight 定义了接口 Draw(Contex* pContex)

CharacterFlyweight 存储内部状态的类并实现Draw(Contex* pContex). 有一个m_char存储字母(它就是内部状态了).

Client 管理ContexCharacterFactory::m_char的关系.

Client不一定只对Log操作它也可以对TXT, XML, SelfDefine类操作根据需求而定.

如图:


图1

代码

CharacterFactory GetCharacter(char ch)
{
	for c in FlyweightList
		if c.m_char == ch
			return c
	
	return new CharacterFactory(ch)
}

CharacterFlyweight::Draw(Contex* pContex)
{
	...
}

// Client 调用
Flyweight* pFlyweight = CharacterFactory::GetCharacter('a');
// 计算'a'的Contex(算法计算也行, 存储也行)
...
// 绘制
pFlyweight->Draw(pContex);

// 

我的理解

1. 刚看书中的例子时就是不明白书中的文档编辑器使用Flyweight模式是怎样的省内存

例如 "aaabbbcccddd" 这段字符长度是12字节, 3a, 3b, 3c, 3d, 加上12个字母的位置字体颜色信息, 12Context对象如果字母a, b, c, d共享了就编程4 + 12Context对象就省了8个字节但是有一个问题就是共享的话使用者需要存储字符的指针一个字符的指针需要的容量比一个字母要多啊所以总是认为为了一个字节的字母而使用Flyweight模式好像并没有什么好处吧(这种情况是没有什么好处的).

2. 自己弄错了省空间是一个方面而看看Flyweight模式的的意图(运用共享技术有效地支持大量细粒度的对象), 这种小粒度对象的频繁创建是很占开销的.

3. 在文档编辑器处理中 字母有内部状态, Context也有内部状态(例如Context中的字体也是有限的颜色也是有限的), 这可以作为Context的内部状态从而再分出了另一维度的Flyweight, 此时内存空间就真的大大减少了.

如图 :( 这里用了两个Flyweight模式)

图2

4. 另外, Flyweight的意图与pool思想的意图是相同的都是为了避免对象的频繁创建销毁.

但是有区别的, Flyweight的内部状态是一致的公共的pool中的对象的状态是各管各的用户使用pool中的对象是可以改变对象中的状态的Flyweight则不行因为Flyweight是共享的更细致的说就是FlyweightFactory的实现可以使用pool的思想来管理Flyweight对象. Flyweight处理使用了pool思想外还强调要把内部状态和外部状态分离而且内部状态和外部状态存在映射关系这种关系需要一定的策略来管理(动态计算或者静态存储都可以看需求).

【上篇】
【下篇】

抱歉!评论已关闭.