概述
想想我们编辑文档用的wps,文档里文字很多都是重复的,我们不可能为每一个出现的汉字都创建独立的空间,这样代价太大,最好的办法就是共享其中相同的部分,使得需要创建的对象降到最小,这个就是享元模式的核心,即运用共享技术有效地支持大量细粒度的对象。
享元对象能做到共享的关键是区分内蕴状态(InternalState)和外蕴状态(ExternalState)。内蕴状态是存储在享元对象内部并且不会随环境改变而改变。因此内蕴状态并可以共享。
外蕴状态是随环境改变而改变的、不可以共享的状态。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。外蕴状态与内蕴状态是相互独立的。
类图与样例
抽象享元类(Flyweight)
它是所有具体享元类的超类。为这些类规定出需要实现的公共接口,那些需要外蕴状态(Exte的操作可以通过方法的参数传入。抽象享元的接口使得享元变得可能,但是并不强制子类实行共享,因此并非所有的享元对象都是可以共享的。
具体享元类(ConcreteFlyweight)
具体享元类实现了抽象享元类所规定的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。享元对象的内蕴状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。有时候具体享元类又称为单纯具体享元类,因为复合享元类是由单纯具体享元角色通过复合而成的。
不能共享的具体享元类(UnsharableFlyweight)
不能共享的享元类,又叫做复合享元类。一个复合享元对象是由多个单享元对象组成,这些组成的对象是可以共享的,但是复合享元类本身并不能共享。
享元工厂类(FlyweightFactoiy)
享元工厂类负责创建和管理享元对象。当一个客户端对象请求一个享元对象的时候,享元工厂需要检查系统中是否已经有一个符合要求的享元对象,如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有适当的享元对象的话,享元工厂角色就应当创建一个新的合适的享元对象。
客户类(Client)
客户类需要自行存储所有享元对象的外蕴状态。
// CplusplusFlyweight.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <map>
using namespace std;
class Character
{
public:
virtual ~Character(){};
virtual void SetSize(int, int) = 0;
virtual void Display() = 0;
protected:
Character(){};
char m_chSymbol;
int m_nWeight;
int m_nHeight;
};
class CharacterA : public Character
{
public:
CharacterA();
virtual ~CharacterA();
void SetSize(int, int);
void Display();
};
CharacterA::CharacterA()
{
this->m_chSymbol = 'A';
this->m_nWeight = 100;
this->m_nHeight = 200;
}
CharacterA::~CharacterA()
{
}
void CharacterA::SetSize(int nWeight, int nHeight)
{
this->m_nWeight = nWeight;
this->m_nHeight = nHeight;
}
void CharacterA::Display()
{
cout << "CharacterA:" << m_chSymbol << "(" << m_nWeight << "," << m_nHeight << ")" << endl;
}
class CharacterB : public Character
{
public:
CharacterB();
virtual ~CharacterB();
void SetSize(int, int);
void Display();
};
CharacterB::CharacterB()
{
this->m_chSymbol = 'B';
this->m_nWeight = 100;
this->m_nHeight = 200;
}
CharacterB::~CharacterB()
{
}
void CharacterB::SetSize(int nWeight, int nHeight)
{
this->m_nWeight = nWeight;
this->m_nHeight = nHeight;
}
void CharacterB::Display()
{
cout << "CharacterB:" << m_chSymbol << "(" << m_nWeight << "," << m_nHeight << ")" << endl;
}
class CharacterFactory
{
public:
CharacterFactory();
virtual ~CharacterFactory();
Character* GetCharacter(char);
private:
std::map<char, Character*> m_mChar;
};
CharacterFactory::CharacterFactory()
{
m_mChar.insert(make_pair<char, Character*>('A', new CharacterA));
m_mChar.insert(make_pair<char, Character*>('B', new CharacterB));
}
CharacterFactory::~CharacterFactory()
{
}
Character* CharacterFactory::GetCharacter(char chIn)
{
map<char, Character*>::iterator it = m_mChar.find(chIn);
if(it != m_mChar.end())
{
return (Character*)it->second;
}
return NULL;
}
int _tmain(int argc, _TCHAR* argv[])
{
CharacterFactory* pFactory = new CharacterFactory;
//内蕴状态 存储在享元对象内部并且不会随环境改变而改变
Character* ch1 = pFactory->GetCharacter('A');
ch1->Display();
//外蕴状态 客户端保存
Character* ch2 = pFactory->GetCharacter('B');
ch2->SetSize(500, 800);
ch2->Display();
return 0;
}
要点
1、面向对象很好的解决了抽象性的问题,但是作为一个运行在机器中的程序实体,我们需要考虑对象的代价问题。Flyweight设计模式主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。
2、Flyweight采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实现方面,要注意对象状态的处理。
3、享元模式的优点在于它大幅度地降低内存中对象的数量。但是,它做到这一点所付出的代价也是很高的:享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。另外它将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。
适用性
当以下所有的条件都满足时,可以考虑使用享元模式:
1、一个系统有大量的对象。
2、这些对象耗费大量的内存。
3、这些对象的状态中的大部分都可以外部化。
4、这些对象可以按照内蕴状态分成很多的组,当把外蕴对象从对象中剔除时,每一个组都可以仅用一个对象代替。
5、软件系统不依赖于这些对象的身份,换言之,这些对象可以是不可分辨的。
满足以上的这些条件的系统可以使用享元对象。最后,使用享元模式需要维护一个记录了系统已有的所有享元的表,而这需要耗费资源。因此,应当在有足够多的享元实例可供共享时才值得使用享元模式。
优缺点
享元模式的优点在于它大幅度地降低内存中对象的数量。但是,它做到这一点所付出的代价也是很高的:
1、享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。
2、享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。
LCL_data原创于CSDN.NET【http://blog.csdn.net/lcl_data/article/details/8974679】
分享到:
相关推荐
设计模式(C#)之享元模式(Flyweight Pattern),运用共享技术有效地支持大量细粒度的对象。
主要为大家详细介绍了C++设计模式之享元模式Flyweight,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
23种设计模式(Design Pattern)的C++实现范例,包括下面列出的各种模式,代码包含较详细注释。另外附上“设计模式迷你手册.chm” 供参考。 注:项目在 VS2008 下使用。 创建型: 抽象工厂模式(Abstract Factory) ...
C++设计模式课件13_Flyweight_享元模式.pdf
11. 享元模式(Flyweight Pattern) 12. 代理模式(Proxy Pattern) 行为型 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 16. 观察者模式(Observer Pattern...
设计模式学习笔记--Flyweight享元模式.docx设计模式学习笔记--Flyweight享元模式.docx设计模式学习笔记--Flyweight享元模式.docx设计模式学习笔记--Flyweight享元模式.docx设计模式学习笔记--Flyweight享元模式.docx
C++设计模式代码资源13_Flyweight.zip
实现对象的复用——享元模式(二) 实现对象的复用——享元模式(三) 实现对象的复用——享元模式(四) 实现对象的复用——享元模式(五) 代理模式-Proxy Pattern 设计模式之代理模式(一) 设计模式之代理模式...
设计模式精解- GoF 23 种设计模式解析附 C++实现源码 目 录 0 引言 ...........................................................................................................................................
主要介绍了C++设计模式编程的Flyweight享元模式结构,享元模式在实现过程中主要是要为共享对象提供一个存放的"仓库"(对象池),需要的朋友可以参考下
抽象享元(Flyweight)角色:此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口。那些需要外蕴状态的操作可以通过调用商业以参数形式传入 具体享元(ConcreteFlyweight)角色:实现Flyweight接口,并为...
享元模式(Flyweight Pattern) 代理模式(Proxy Pattern) 3. 行为型模式 责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式...
2.5 Flyweight模式..................................................................................................................44 2.6 Facade模式.......................................................
设计模式——享元模式 享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度的对象 对一个类进行的实例,只在第一次使用时建立,其他时候是用同一个实例,减少内存的开销 """ # 抽象网站类 class Web
c++设计模式-结构型模式-享元模式;qt工程;c++简单源码; 享元(Flyweight)模式的定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类...
设计模式 Flyweight
C#面向对象设计模式纵横谈(12):Flyweight 享元模式(结构型模式) (Level 300)