• 享元模式 设计模式学习


      享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。

      下面给出享元模式的结构图:

          

      下面给出享元模式的基本代码结构:

    namespace ConsoleApplication1
    {
        //Flyweight类,它是所有具体享元类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态
        abstract class Flyweight
        {
            public abstract void Operation(int extrinsicstate);
        }
    
        //ConcreteFlyweight是继承Flyweight或实现Flyweight接口,并为内部状态增加存储空间
        class ConcreteFlyweight : Flyweight
        {
            public override void Operation(int extrinsicstate)
            {
                Console.WriteLine("具体Flyweight:" + extrinsicstate);
            }
        }
    
        //UnsharedConcreteFlyweight是指那些不需要共享的Flyweight子类。因为Flyweight接口共享称为可能,但它并不强制共享
        class UnsharedConcreteFlyweight : Flyweight
        {
            public override void Operation(int extrinsicstate)
            {
                Console.WriteLine("不共享的具体Flyweight:" + extrinsicstate);
            }
        }
    
        //FlyweightFactory,是一个享元工厂,用来创建并管理Flyweight对象。它主要是用来确保合理地共享Flyweight
        //当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例,如不存在则创建一个。
        class FlyweightFactory
        {
            private Hashtable flyweights = new Hashtable();
    
            public FlyweightFactory()   //初始化工厂,先生成3个实例
            {
                flyweights.Add("X", new ConcreteFlyweight());
                flyweights.Add("Y", new ConcreteFlyweight());
                flyweights.Add("Z", new ConcreteFlyweight());
            }
                
            public Flyweight GetFlyweight(string key)   //根据客户端请求,获得已生成实例
            {
                return ((Flyweight)flyweights[key]);
            }
        }
     
        class Program
        {
            static void Main(string[] args)
            {
                int extrinsicstate = 22;    //代码外部状态
    
                FlyweightFactory f = new FlyweightFactory();
    
                Flyweight fx = f.GetFlyweight("X");
                fx.Operation(--extrinsicstate);
    
                Flyweight fy = f.GetFlyweight("Y");
                fx.Operation(--extrinsicstate);
    
                Flyweight fz = f.GetFlyweight("Z");
                fx.Operation(--extrinsicstate);
    
                Flyweight uf = new UnsharedConcreteFlyweight();
                uf.Operation(--extrinsicstate);
    
                Console.ReadKey();
            }
        }  
    }

      结果如图所示:

      

      UnsharedConcreteFlyweight用于解决那些不需要共享对象的问题。因为享元模式在使用的时候,既有需要共享的部分也有不需要共享的部分,此时UnsharedConcreteFlyweight的作用就出来了。

      享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能够受大幅地减少需要实例化的类的数量。如果能把那些参数移到类实例的外面,在方法调用时将他们传递进来,就可以通过共享大幅度地减少单个实例的数目。

      在现实中什么时候才应该考虑使用享元模式呢?

      如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。

      下面回到《大话设计模式》里面的网站建设的例子:

    namespace ConsoleApplication1
    {
        //用户
        public class User
        {
            private string name;
            public User(string name)
            {
                this.name = name;
            }
    
            public string Name
            {
                get { return name; }
            }
        }
    
        //网站抽象类
        abstract class WebSite
        {
            public abstract void Use(User user);    //"使用"方法需要传递"用户"对象
        }
    
        //具体网站类
        class ConcreteWebSite : WebSite
        {
            private string name = "";
    
            public ConcreteWebSite(string name)
            {
                this.name = name;
            }
    
            public override void Use(User user)     //实现"Use"方法
            {
                Console.WriteLine("网站分类:" + name + " 用户:" + user.Name);
            }
        }
    
        //网站工厂类
        class WebSiteFactory
        {
            private Hashtable flyweights = new Hashtable();
    
            //获得网站分类
            public WebSite GetWebSiteCategory(string key)
            {
                if (!flyweights.ContainsKey(key))
                {
                    flyweights.Add(key, new ConcreteWebSite(key));
                }
                return ((WebSite)flyweights[key]);
            }
    
            //获得网站分类总数
            public int GetWebSiteCount()
            {
                return flyweights.Count;
            }
        }
     
        class Program
        {
            static void Main(string[] args)
            {
                WebSiteFactory f = new WebSiteFactory();
    
                WebSite ws1 = f.GetWebSiteCategory("产品展示");
                ws1.Use(new User("小菜"));
    
                WebSite ws2 = f.GetWebSiteCategory("产品展示");
                ws1.Use(new User("大鸟"));
    
                WebSite ws3 = f.GetWebSiteCategory("产品展示");
                ws1.Use(new User("娇娇"));
    
                WebSite ws4 = f.GetWebSiteCategory("博客");
                ws1.Use(new User("关羽"));
    
                WebSite ws5 = f.GetWebSiteCategory("博客");
                ws1.Use(new User("张飞"));
    
                WebSite ws6 = f.GetWebSiteCategory("博客");
                ws1.Use(new User("赵云"));
    
                Console.WriteLine("得到网站分类的总数为{0}",f.GetWebSiteCount());
    
                Console.ReadKey();
            }
        }  
    }

      结果如下图所示:

        

  • 相关阅读:
    【css】所有的a标签设置为新窗口打开【原创】
    TP 3.1版本不支持 CONTROLLER_NAME
    关于TP 特殊页面伪静态规则的编写 研究实现
    larave PHP框架
    [转]git和github
    [转]mysql语句大全
    camera.swf?  提示  图片上传中请稍候,没任何报错
    mysql大小写敏感(默认为1,不敏感)
    数据cube的schema与sql的对应的关系
    MDX的实例讲解(排名前15的小例子)
  • 原文地址:https://www.cnblogs.com/kissdodog/p/2977933.html
Copyright © 2020-2023  润新知