享元模式(Flyweight Pattern)
当系统中存在大量相同或者相似的对象时,可以考虑使用享元模式,它通过共享技术实现相同或相似的细粒度对象的复用,从而节约内存空间,提高系统性能。
在享元模式提供一个享元池用于存储已经创建好的享元对象,并通过享元工厂类将享元对象提供给其他客户端使用。享元池:存储这些共享实例对象的地方
避免了系统中出现相同或者相似的对象,同时又不影响客户端程序通过面向对象发方式对这些对象进行操作。
享元模式:运用共享技术有效地支持大量细粒度对象的复用。
享元对象能共享的关键是区分了内部状态(Intrinsic State)和外部状态(Extrinsic State)。
内部状态:存储在享元对象内部并且不会随环境改变而改变的状态,内部状态可以共享。
外部状态:随环境改变而改变、不可以共享的状态。
享元模式由4种角色:
1.Flyweight(抽象享元类):通常是一个接口或抽象类,在抽象享元类中声明具体享元类公共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时可以通过这些方法来设置外部数据(外部状态)
2.ConcreteFlyweight(具体享元类):实现抽象享元类,其实例称为享元对象,并在具体享元类中为内部状态提供了存储空间。通常可以结合单例模式来设计具体享元类。为每一个具体享元类提供唯一的享元对象。
3.UnsharedConcreteFlyweight(非共享具体享元类):并不是所有子类都需要被共享,当需要一个非共享具体享元类的对象可以直接通过实例化创建。
4.FlyweightFactory(享元工厂类):用于创建并管理享元对象,将各个类型的具体享元对象存储在一个享元池中,享元池一般被设计为一个“键值对”集合。当用户请求一个具体的享元对象时,享元工厂提供一个存储在享元池中已创建的实例或创建一个新的实例(如果不存在),返回新创建的实例并将其存储在享元池中。
抽象享元类:
abstract class Flyweight
{
public abstract void Operation(string extrinsicState);
}
具体享元类:
class ConcreteFlyweight:Flyweight
{
//内部状态intrinsicState作为成员变量,同一个享元对象其内部状态时一致的
private string intrinsicState;
public ConcreteFlyweight(string intrinsicState)
{
this.intrinsicState = intrinsicState;
}
//外部状态extrinsicState在使用时由外部设置,不保存在享元对象中,即使是同一个对象,在每一次调用时可以传入不同的外部状态
public override void Operation(string extrinsicState)
{
//实现业务方法
}
}
非共享具体享元类:
class UnsharedConcreteFlyweight:Flyweight
{
public override void Operation(string extrinsicState)
{
//实现业务方法
}
}
享元工厂类:
using System.Collections;
class FlyweightFactory
{
//定义一个Hashtable用于存储享元对象,实现享元池
private Hashtable flyweights = new Hashtable();
public Flyweight GetFlyweight(string key)
{
//如果对象存在,则直接从享元池中获取
if(flyweights.ContainsKey(key))
{
return (Flyweight)flyweights[key];
}
//如果对象不存在,先创建一个新的对象添加到享元池中,然后返回
else
{
Flyweight fw = new ConcreteFlyweight("state");
flyweight.Add(key,fw);
return fw;
}
}
}