享元模式 -- 大话设计模式

在今天,读书有时是件“麻烦”事。它需要你付出时间,付出精力,还要付出一份心境。--仅以《大话设计模式》来祭奠那逝去的……

享元模式:运用共享技术有效地支持大量细粒度的对象,避免大量的相似对象的开销

程序设计中,有时需要大量细粒度的对象。如果能从这些对象中发现除了几个参数不同其他都是相同的话,可以通过将这些相同参数移到实例外,构建享元类,在方法调用时将具体对象传进来,来减少享元类被实例化的数目,减少系统消耗

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));
            }
        }

 

posted @ 2015-11-05 14:47  荒古禁地  阅读(226)  评论(0编辑  收藏  举报