在今天,读书有时是件“麻烦”事。它需要你付出时间,付出精力,还要付出一份心境。--仅以《大话设计模式》来祭奠那逝去的……
享元模式:运用共享技术有效地支持大量细粒度的对象,避免大量的相似对象的开销
程序设计中,有时需要大量细粒度的对象。如果能从这些对象中发现除了几个参数不同其他都是相同的话,可以通过将这些相同参数移到实例外,构建享元类,在方法调用时将具体对象传进来,来减少享元类被实例化的数目,减少系统消耗
1.网页游戏刷屏怪物
千万怪物灵魂,来到轮回工厂。工厂将灵魂放入生产线,赋予种族模板和皮肤模板(假设一款游戏,有3种怪物,每一种怪物样子都一样,boss和小怪只有皮肤颜色不同。如果怪物的属性是名字、样子和皮肤颜色,那么我们实例化一只怪物的时候,同时需要实例化一次样子和皮肤。数量少的话,还无所谓,一旦要实例化10W、100W只怪物的话,我们就需要实例化10W、100W次样子和皮肤,系统承担很大的内存消耗。通过观察,怪物的样子数量是固定的,皮肤颜色也是固定的,我们可以将这两个属性共享出去,这样实例化怪物的时候,就减少了样子和皮肤的实例化对象数量)
定义享元类的超类或者接口,可以接受或者作用于外部状态
///
/// 具体享元类的超类或者接口(可以接受或者作用于外部状态)
///
public abstract class Flyweight
{
///
/// 颜色(内部状态)
///
public string Colour { get; set; }
///
/// 种类(内部状态)
///
public string Kind { get; set; }
///
/// 操作flyweight使用者
///
/// flyweight使用者(外部状态)
public abstract void Operation(string obj);
}
定义怪物模型,具体的享元类,为内部状态增加存储空间
///
/// 怪物模型类(具体享元类,为内部状态增加存储空间)
///
public class MonsterModel : Flyweight
{
///
/// 给怪物灵魂赋予种族和皮肤
///
/// 怪物灵魂
public override void Operation(string obj)
{
Console.WriteLine("{0},系统大神赋予了我{1}种族的样子和{2}的皮肤,哇咔咔~我来了,菜鸟们~", obj, this.Kind, this.Colour);
}
}
定义享元工厂,用来创建和管理享元对象。确保合理的共享享元对象,当用户请求一个享元对象时,工厂提供一个已创建的或者创建一个(如果不存在的话),这里可以同单例模式一起使用
///
/// 享元工厂(用来创建和管理享元对象。确保合理的共享享元对象,当用户请求一个享元对象时,工厂提供一个已创建的实例或创建一个(如果不存在的话))
///
public class FlyweightFactory
{
public Hashtable flyweights = new Hashtable();
public FlyweightFactory()
{
flyweights.Add("白色史莱姆", new MonsterModel() { Kind = "史莱姆", Colour = "白色" });
flyweights.Add("蓝色史莱姆", new MonsterModel() { Kind = "史莱姆", Colour = "蓝色" });
flyweights.Add("紫色史莱姆", new MonsterModel() { Kind = "史莱姆", Colour = "紫色" });
}
public Flyweight GetFlyweight(string key)
{
return (Flyweight)flyweights[key];
}
}
开启场景模拟
static void Main(string[] args)
{
//千万怪物灵魂
string model = "我是万千怪物灵魂中的{0}号";
//来到轮回工厂
FlyweightFactory factory = new FlyweightFactory();
//工厂将灵魂放入生产线
for (int n = 0; n < 10; n++)
{
//赋予种族模板和皮肤模板
factory.GetFlyweight("白色史莱姆").Operation(string.Format(model, n));
}
}