苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper万能框架(V2.3-含.netcore) HttpHelper官方出品,无敌框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 最牛的爬虫类,没有爬不到只有想不到 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 473|回复: 3

[学习心得] C#享元模式列子

[复制链接]
发表于 2019-1-8 13:43:01 | 显示全部楼层 |阅读模式
一 、  一个咖啡摊的例子

      在这个咖啡摊(Coffee Stall)所使用的系统里,有一系列的咖啡"风味(Flavor)"。客人到摊位上购买咖啡,所有
的咖啡均放在台子上,客人自己拿到咖啡后就离开摊位。咖啡有内蕴状态,也就是咖啡的风味;咖啡没有环境因
素,也就是说没有外蕴状态。如果系统为每一杯咖啡都创建一个独立的对象的话,那么就需要创建出很多的细小
对象来。这样就不如把咖啡按照种类(即"风味")划分,每一种风味的咖啡只创建一个对象,并实行共享。
使用咖啡摊主的语言来讲,所有的咖啡都可按"风味"划分成如 Capucino、Espresso 等,每一种风味的咖啡不
论卖出多少杯,都是全同、不可分辨的。所谓共享,就是咖啡风味的共享,制造方法的共享等。因此,享元模式
对咖啡摊来说,就意味着不需要为每一份单独调制。摊主可以在需要时,一次性地调制出足够一天出售的某一种
风味的咖啡。


很显然,这里适合使用单纯享元模式。系统的设计如下:


[C#] 纯文本查看 复制代码
using System;
using System.Collections;

namespace JobApi
{
    public abstract class Order
    {
        // 将咖啡卖给客人
        public abstract void Serve();
        // 返回咖啡的名字
        public abstract string GetFlavor();
    }
    public class Flavor : Order
    {
        private readonly string flavor;
        // 构造函数,内蕴状态以参数方式传入
        public Flavor(string flavor)
        {
            this.flavor = flavor;
        }
        // 返回咖啡的名字
        public override string GetFlavor()
        {
            return flavor;
        }
        // 将咖啡卖给客人
        public override void Serve()
        {
            Console.WriteLine("Serving flavor " + flavor);
        }
    }
    public class FlavorFactory
    {
        private readonly Hashtable flavors = new Hashtable();
        public Order GetOrder(string key)
        {
            if (!flavors.ContainsKey(key))
                flavors.Add(key, new Flavor(key));
            return ((Order)flavors[key]);
        }
        public int GetTotalFlavorsMade()
        {
            return flavors.Count;
        }
    }
    public class Client
    {
        private static FlavorFactory flavorFactory;
        private static int ordersMade;
        public static void Main(string[] args)
        {
            flavorFactory = new FlavorFactory();
            TakeOrder("Black Coffee");
            TakeOrder("Capucino");
            TakeOrder("Espresso");
            TakeOrder("Capucino");
            TakeOrder("Espresso");
            TakeOrder("Black Coffee");
            TakeOrder("Espresso");
            TakeOrder("Espresso");
            TakeOrder("Black Coffee");
            TakeOrder("Capucino");
            TakeOrder("Capucino");
            TakeOrder("Black Coffee");
            Console.WriteLine("\nTotal Orders made: " + ordersMade);
            Console.WriteLine("\nTotal Flavor objects made: " +
                              flavorFactory.GetTotalFlavorsMade());
        }
        private static void TakeOrder(string aFlavor)
        {
            Order o = flavorFactory.GetOrder(aFlavor);
            // 将咖啡卖给客人
            o.Serve();
            ordersMade++;
        }
    }
}


二 、  咖啡屋的例子
      在前面的咖啡摊项目里,由于没有供客人坐的桌子,所有的咖啡均没有环境的影响。换言之,咖啡仅有内蕴状态,
也就是咖啡的种类,而没有外蕴状态。

      下面考虑一个规模稍稍大一点的咖啡屋(Coffee Shop)项目。屋子里有很多的桌子供客人坐,系统除了需要提供
咖啡的"风味"之外,还需要跟踪咖啡被送到哪一个桌位上,因此,咖啡就有了桌子作为外蕴状态。

由于外蕴状态的存在,没有外蕴状态的单纯享元模式不再符合要求。系统的设计可以利用有外蕴状态的单纯享元

模式。系统的代码如下:


[C#] 纯文本查看 复制代码
using System;
using System.Collections;

namespace JobApi
{
    public abstract class Order
    {
        // 将咖啡卖给客人
        public abstract void Serve(Table table);
        // 返回咖啡的名字
        public abstract string GetFlavor();
    }
    public class Flavor : Order
    {
        private readonly string flavor;
        // 构造函数,内蕴状态以参数方式传入
        public Flavor(string flavor)
        {
            this.flavor = flavor;
        }
        // 返回咖啡的名字
        public override string GetFlavor()
        {
            return flavor;
        }
        // 将咖啡卖给客人
        public override void Serve(Table table)
        {
            Console.WriteLine("Serving table {0} with flavor {1}", table.Number, flavor);
        }
    }
    public class FlavorFactory
    {
        private readonly Hashtable flavors = new Hashtable();
        public Order GetOrder(string key)
        {
            if (!flavors.ContainsKey(key))
                flavors.Add(key, new Flavor(key));
            return ((Order)flavors[key]);
        }
        public int GetTotalFlavorsMade()
        {
            return flavors.Count;
        }
    }
    public class Table
    {
        private readonly int number;
        public Table(int number)
        {
            this.number = number;
        }
        public int Number
        {
            get { return number; }
        }
    }
    public class Client
    {
        private static FlavorFactory flavorFactory;
        private static int ordersMade;
        public static void Main(string[] args)
        {
            flavorFactory = new FlavorFactory();
            TakeOrder("Black Coffee");
            TakeOrder("Capucino");
            TakeOrder("Espresso");
            TakeOrder("Capucino");
            TakeOrder("Espresso");
            TakeOrder("Black Coffee");
            TakeOrder("Espresso");
            TakeOrder("Espresso");
            TakeOrder("Black Coffee");
            TakeOrder("Capucino");
            TakeOrder("Capucino");
            TakeOrder("Black Coffee");
            Console.WriteLine("\nTotal Orders made: " + ordersMade);
            Console.WriteLine("\nTotal Flavor objects made: " +
                              flavorFactory.GetTotalFlavorsMade());
        }
        private static void TakeOrder(string aFlavor)
        {
            Order o = flavorFactory.GetOrder(aFlavor);
            // 将咖啡卖给客人
            o.Serve(new Table(++ordersMade));
        }
    }
}


三 、  享元模式应当在什么情况下使用


当以下所有的条件都满足时,可以考虑使用享元模式:

 一个系统有大量的对象。
 这些对象耗费大量的内存。
 这些对象的状态中的大部分都可以外部化。
 这些对象可以按照内蕴状态分成很多的组,当把外蕴对象从对象中剔除
时,每一个组都可以仅用一个对象代替。
 软件系统不依赖于这些对象的身份,换言之,这些对象可以是不可分辨的。

满足以上的这些条件的系统可以使用享元对象。

最后,使用享元模式需要维护一个记录了系统已有的所有享元的表,而这需要耗费资源。因此,应当在有足够多
的享元实例可供共享时才值得使用享元模式。

四 、  享元模式的优点和缺点

享元模式的优点在于它大幅度地降低内存中对象的数量。但是,它做到这一点所付出的代价也是很高的:

 享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部
化,这使得程序的逻辑复杂化。
 享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变
长。

发表于 2019-1-8 14:29:39 | 显示全部楼层
发表于 2019-1-8 16:40:58 | 显示全部楼层
发表于 2019-1-8 16:43:28 | 显示全部楼层
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备17001017号-1)

GMT+8, 2019-12-7 23:04

© 2017-2018

快速回复 返回顶部 返回列表