FlyWeight模式——设计模式学习笔记

来源:互联网 发布:网络局域网上不了 编辑:程序博客网 时间:2024/06/06 00:48

FlyWeight模式

一 意图

运用共享技术有效地支持大量细粒度的对象。

二 动机

      有些应用程序得益于在其整个设计过程中采用对象技术,但简单化的实现代价极大。

使用面向对象的抽象化,可能会造成庞大的对象群,造成空间的巨大消耗,而影响性能。

在文档编辑器例子中如果一个字符对应一个对象,那么一篇文档所要容纳的对象将是非常的庞大耗费大量的内存。

  而实际组成文档的字符是有限的,是由这些字符不同的组合和排列得到的。

所以需要共享,将基本的字符进行共享,将使得字符对象变得有限。

Flyweight只存储相应的字符代码

这里的关键概念是内部状态外部状态之间的区别。

  内部状态存储于flyweight中,它包含了独立于flyweight场景的信息,这些信息使得flyweight可以被共享。

如字符代码,字符大小……

  外部状态取决于flyweight场景,并根据场景而变化,因此不可共享。用户对象负责在必要的时候将外部状态传递给flyweight。

如字符位置,字符颜色……


三 适用性及其结构

当以下情况都成立时使用Flyweight模式:

•一个应用程序使用了大量的对象。

• 完全由于使用大量的对象,造成很大的存储开销。

• 对象的大多数状态都可变为外部状态。

• 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。

• 应用程序不依赖于对象标识。由于Flyweight对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。

结构:


description:

•Flyweight

— 描述一个接口,通过这个接口Flyweight可以接受并作用于外部状态。

• ConcreteFlyweight

— 实现Flyweight接口, 并为内部状态( 如果有的话) 增加存储空间。

ConcreteFlyweight对象必须是可共享的。它所存储的状态必须是内部的;即,它必

须独立于Concrete Flyweight对象的场景。

• UnsharedConcreteFlyweight

— 并非所有的Flyweight子类都需要被共享。Flyweight接口使共享成为可能,但它并不强制共享。在Flyweight对象结构的某些层次, UnsharedConcreteFlyweight对象通常

将ConcreteFlyweight对象作为子节点(Row和Conum就是这样)。

• FlyweightFactory

— 创建并管理Flyweight对象。

— 确保合理地共享Flyweight。当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。

• Client

— 维持一个对Flyweight的引用。

— 计算或存储一个(多个)Flyweight的外部状态。

 

Analysis:

  Flyweight执行时所需的状态必定是内部的或外部的。内部状态存储于ConcreteFlyweight对象之中;

而外部对象则由C l i e n t对象存储或计算。当用户调用Flyweight对象的操作时,将该状态传递给它。

• 用户不应直接对ConcreteFlyweight类进行实例化,而只能从FlyweightFactory对象得到ConcreteFlyweight对象,

  这可以保证对它们适当地进行共享。

存储节约由以下几个因素决定:

• 因为共享,实例总数减少的数目

• 对象内部状态的平均数目

• 外部状态是计算的还是存储的

 

四 代码实现

Note:

删除外部状态:该模式的可用性在很大程度上取决于是否容易识别外部状态并将它从

共享对象中删除

管理共享对象:引用计数和垃圾回收……

Example :象棋中的棋局中的棋子,任何棋局都是32个 棋子的不同组合。

1 Flyweight

Chess提供了外部状态的设置

复制代码
/*----------------------------------------------------------------*/
/* class Object */
/*----------------------------------------------------------------*/
class Object
{

};

/*----------------------------------------------------------------*/
/* class Chess */
/*----------------------------------------------------------------*/
class Chess: public Object
{
public:
Chess(){}
void setShape(int shape){}
void setSize(int size){}
void setHeight(int height){}
void setPos(int pos){}
virtual void draw()
{
cout<<"Chess draw"<<endl;
}
private:
int m_shape;
int m_size;
int m_height;
int m_pos;
};
复制代码

 

CChess保存内部状态

复制代码
/*----------------------------------------------------------------*/
/* class CChess */
/*----------------------------------------------------------------*/
class CChess: public Chess
{
public:
CChess(int code)
{
m_code = code;
}
virtual void draw()
{
cout<<"CChess draw"<<endl;
}
private:
int m_code;
};
复制代码


ChessFactory提供创建享元CChess的接口

复制代码
/*----------------------------------------------------------------*/
/* class ChessFactory */
/*----------------------------------------------------------------*/
class ChessFactory: public Object
{
#define CHECSS_MAX_NUM (16)
#define CHESS_CODE_OFFSET (0x1000)
class ChessCodeMap
{
public:
int m_code;
CChess* m_chess;
};
public:
ChessFactory()
{
for (int i = 0; i < CHECSS_MAX_NUM; i++)
{
m_chessMap[i].m_chess = NULL;
m_chessMap[i].m_code = i;
}
}
CChess* createChess(int code)
{
for (int i = 0; i < CHECSS_MAX_NUM; i++)
{
if (m_chessMap[i].m_code == code)
{
if (m_chessMap[i].m_chess == NULL)
{
m_chessMap[i].m_chess = new CChess(code);
}

return m_chessMap[i].m_chess;
}
}

return NULL;
}
private:
ChessCodeMap m_chessMap[CHECSS_MAX_NUM];
};
复制代码


Test

 

复制代码
#include "flyweight.h"

int main()
{
ChessFactory* chessFc = new ChessFactory();
CChess* chess = chessFc->createChess(1);
chess->draw();

return 0;
}
复制代码
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电脑中了感染病毒杀不干净怎么办 电脑下载的软件有病毒了怎么办 电脑强制关机后开不了机怎么办 受刺激后出现精神异常该怎么办 当屏幕出现暂时无法移动时怎么办 英雄联盟欧服连接不上服务器怎么办 试客联盟认证手机号成空号了怎么办 汽车脚垫不贴合翘起来了怎么办 版权保护迅雷下载不了的资源怎么办 30岁在外地城市找不到工作怎么办 新买的苹果爱拍充不进去电是怎么办 绝地求生东南亚服匹配不到人怎么办 电脑卡住了怎么办鼠标也点不动 幽灵行动荒野没有主线任务了怎么办 拼多多购买的东西下架了怎么办 电脑版的荒野行动玩的时候卡怎么办 欧洲卡车模拟2气压过低怎么办 word页眉和正文有段距离怎么办 酷派大神x7卡在开机界面怎么办 妹妹结婚跟领导请假不批怎么办 网页分享后不想显示连接网址怎么办 魔兽世界肉弹随从的任务断了怎么办 在美发店上班被小混混打了怎么办 孩子上四年级了不知道写作业怎么办 运动完第二天恶心想吐怎么办 吃减肥药皮肤变差了怎么办 生了孩子子宫没恢复好怎么办 cf我是新手不知道怎么报点怎么办 挑战人物已经有了又刷到怎么办 小米手机账户验证码隐藏了怎么办? 苹果手机绑定的邮箱密码忘了怎么办 魔域手机版不要的装备怎么办 魔域永恒多了的幻兽装备怎么办 魔域怀旧版70星以后宝宝怎么办 天猫确认收货后不寄发票怎么办 足球运动员踢了一半想撒尿了怎么办 17个月宝宝0型腿怎么办 走的路多了腿疼怎么办 如果新兵老被老兵打怎么办求求个位 做古董拍卖诈骗被警察抓了怎么办 武汉个人社保怎么办停转到海南来