亨元模式(Flyweight):运用共享技术有效地支持大量细粒度的对象。
亨元模式的定义有些抽象,其实主在使用共享对象,节约系统资源,提高性能。亨元模式结构图如下:
亨元模式代码模板:
//Flyweight类,它是所有具体亨元类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态。
class Flyweight
{
public:
void Operation(int extrinsicstate);
};
//ConreteFlyweight是继承Flyweight超类或实现Flyweight接口,并为内部状态增加存储空间
class ConcreteFlyweight: public Flyweight
{
public:
void Operation(int extrinsicstate)
{
cout<<"具体Flyweight:"<<extrinsicstate;
}
};
//UnsharedConcreteFlyweight是指哪些不需要共享Flyweight子类。因为Flyweight接口共享成为可能,但它并不强制共享。
UnsharedConcreteFlyweight:public Flyweight
{
public:
void Operation(int extrinsicstate)
{
cout<<"不共享的具体Flyweight:"<<extrinsicstate;
}
};
//FlyweightFactory是一个亨元工厂,用来创建并管理Flyweight对象。它主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)
class FlyweightFactory
{
private:
Hashtable flyweights = new Hashtable();
public:
//初始化工厂时,先生成三个实例。
//注意:此处可以不用直接先创建三个实例,可以修改GetFlyweight接口,在调用GetFlyweight方法时,不存在则创建新对象;存在则返回已有对象
FlyweightFactory()
{
flyweight.Add("X", new ConcreteFlyweight());
flyweight.Add("Y", new ConcreteFlyweight());
flyweight.Add("Z", new ConcreteFlyweight());
}
//根据客户端请求,获得已生成的实例
Flyweight GetFlyweight(string key)
{
return ((Flyweight)flyweight[key])
}
//也可以不用先创建实例,在调用时
Flyweight GetFlyweight(string key)
{
return ((Flyweight)flyweight[key])
}
};
//客户端代码
void main()
{
int extrinsicstate = 22;//代码外部状态
FlyweightFactory f = new FlyweightFactory();
Flyweight fx = f.GetFlyweight("X");
fx.Operatiopn(--extrinsicstate );
Flyweight fy = f.GetFlyweight("Y");
fy.Operatiopn(--extrinsicstate );
Flyweight fz = f.GetFlyweight("Z");
fz.Operatiopn(--extrinsicstate );
UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight();
uf.OPeration(--extrinsicstate);
}
结果展示:
使用场景:
亨元模式可以避免大量非常相似类的开销。在城西设计中,优势需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能够大幅度地减少需要实例化的类的数量。如果能把哪些参数一道类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。
亨元模式更多应用于底层,但在显示中也有应用。比如围棋、五子棋等游戏的开发工作,存在大量的棋子对象,棋子只有黑白两个色,变化不大,可以将颜色作为棋子的内部状态,各个棋子之间主要的差别时位置不同,位置可以作为棋子的外部状态。棋盘一共有361个空位,按照常规的面向对象方式编程,每放一颗棋子就会生成一个棋子对象,每盘棋都有可能产生两三百个棋子对象,如果有很多个玩家,这对服务器的资源占用非常大。使用亨元模式来处理棋子,那么棋子对象可以减少到只有两个,棋子对象大大减少,大幅度的减少运行时的资源与性能损耗。
亨元模式的缺点:
使用亨元模式需要维护一个记录了系统已有的所有亨元列表,而这本身需要耗费资源,另外亨元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序逻辑复杂化。所以应当在足够多的对象实例可供共享时才值得使用亨元模式