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