zoukankan      html  css  js  c++  java
  • 设计模式之享元模式

    名词解释:

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

    必要元素:

    1.一个享元工厂,用来创建并管理Flyweight对象。它主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在);
    2.所有具体享元类的父类或接口,通过这个接口,Flyweight可以接受并作用于外部状态;
    3.继承Flyweight父类或者实现Flyweight接口,并为内部状态增加存储空间;
    4.指那些不需要共享的Flyweight子类,因为Flyweight接口共享成为可能,但是并不强制共享(即那些不能共享的部分)。

    上例子:

    Flyweight享元抽象类:

      abstract class Flyweight
        {
            public abstract void Operation(int extrinsicstate);
        }

    Flyweight具体共享类:

      class ConcreteFlyweight:Flyweight
        {
            public override void Operation(int extrinsicstate)
            {
                Console.WriteLine("具体Flyweight:"+extrinsicstate);
            }
        }
    
     class UnsharedConcreteFlyweight:Flyweight
        {
            public override void Operation(int extrinsicstate)
            {
                Console.WriteLine("不共享的具体Flyweight:"+extrinsicstate);
            }
        }

    享元工厂:

      class FlyweightFactory
        {
            private Dictionary<string, Flyweight> flyweights = new Dictionary<string, Flyweight>();
            public FlyweightFactory()
            {
                flyweights.Add("X", new ConcreteFlyweight());
                flyweights.Add("Y", new ConcreteFlyweight());
                flyweights.Add("Z", new ConcreteFlyweight());
            }
    
            public Flyweight GetFlyweight(string key)
            {
                return (Flyweight)flyweights[key];
            }
        }

    调用:

                //外部状态
              int extrinsicstate = 22;
    
                FlyweightFactory factory = new FlyweightFactory();
    
                Flyweight fx = factory.GetFlyweight("X");
                fx.Operation(--extrinsicstate);
    
                Flyweight fy = factory.GetFlyweight("Y");
                fx.Operation(--extrinsicstate);
    
                Flyweight fz = factory.GetFlyweight("Z");
                fz.Operation(--extrinsicstate);
    
                Flyweight uf = new UnsharedConcreteFlyweight();
                uf.Operation(--extrinsicstate);
    
                Console.Read();    

     通过享元类父类和子类(共享和非共享部分)以及享元类工厂,构成了享元模式,这样在使用的时候就不会创建多次对象,有效的利用资源。

     例子2(假设有一个网站类,而网站有很多种类型):

    抽象类:

      /// <summary>
        /// 网站抽象类
        /// </summary>
        abstract class WebSite
        {
            public abstract void Use();
        }

    具体网站类:

     /// <summary>
        /// 具体网站类
        /// </summary>
        class ConcreteWebSite:WebSite
        {
            private string name = "";
            public ConcreteWebSite(string name)
            {
                this.name = name;
            }
    
            public override void Use()
            {
                Console.WriteLine("网站分类:"+name);
            }
        }

    网站工厂类:

     /// <summary>
        /// 网站工厂
        /// </summary>
        class WebSiteFactory
        {
            private Dictionary<string, WebSite> flyweights = new Dictionary<string, WebSite>();
            /// <summary>
            /// 获得网站分类
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public WebSite GetWebSite(string key)
            {
                if (!flyweights.ContainsKey(key))
                {
                    flyweights.Add(key, new ConcreteWebSite(key));
                }
                return flyweights[key];
            }
    
            public int GetWebSiteCount()
            {
                return flyweights.Count;
            }
        }

    使用:

               WebSiteFactory factory = new WebSiteFactory();
    
                WebSite fx = factory.GetWebSite("产品展示");
                fx.Use();
    
                WebSite fy = factory.GetWebSite("产品展示");
                fy.Use();
    
                WebSite fz = factory.GetWebSite("产品展示");
                fz.Use();
    
                WebSite fl = factory.GetWebSite("博客");
                fl.Use();
    
                WebSite fm = factory.GetWebSite("博客");
                fm.Use();
    
                WebSite fn = factory.GetWebSite("博客");
                fn.Use();
    
                Console.WriteLine("共有网站{0}个",factory.GetWebSiteCount());
                Console.Read();    

    这样设计基本实现了享元模式的共享对象的目的,也就是说不管创建几个网站,只要是某一类型(博客或者其他),都是完全相同的,但是问题又来了,不同公司的网站应该有不同的账号,所以我们只是体现了共享的部分,还有非共享部分等待我们实现。
    实例2(集成非共享代码):

     外部状态类(User类):

       /// <summary>
        /// 用户类(外部状态)
        /// </summary>
        class User
        {
            private string name;
    
            public string Name
            {
                get { return name; }
            }
    
            public User(string name)
            {
                this.name = name;
            }
        }

    抽象网站类:

      /// <summary>
        /// 网站抽象类
        /// </summary>
        abstract class WebSite
        {
            public abstract void Use(User user);
        }

    方法增加了参数,参数为外部状态对象User。


    具体网站类:

      /// <summary>
        /// 具体网站类
        /// </summary>
        class ConcreteWebSite:WebSite
        {
            private string name = "";
            public ConcreteWebSite(string name)
            {
                this.name = name;
            }
    
            public override void Use(User user)
            {
                Console.WriteLine("网站分类:"+name+" 用户:"+user.Name);
            }
        }

    变化也是User函数添加User对象参数。

    工厂:无变化。

    使用:

            WebSiteFactory factory = new WebSiteFactory();
    
                WebSite fx = factory.GetWebSite("产品展示");
                fx.Use(new User("Colors"));
    
                WebSite fy = factory.GetWebSite("产品展示");
                fy.Use(new User("Blue"));
    
                WebSite fz = factory.GetWebSite("产品展示");
                fz.Use(new User("Listen"));
    
                WebSite fl = factory.GetWebSite("博客");
                fl.Use(new User("Colors.Blue"));
    
                WebSite fm = factory.GetWebSite("博客");
                fm.Use(new User("Listen.Fly"));
    
                WebSite fn = factory.GetWebSite("博客");
                fn.Use(new User("李莫愁"));
    
                Console.WriteLine("共有网站{0}个",factory.GetWebSiteCount());
                Console.Read();

    这样虽然是同一个类型的网站,但是有了User这个外部状态对象,所以就可以把内部状态与外部状态很好的结合。

    总结:

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

  • 相关阅读:
    Pandas速查手册中文版
    MySQL-增删改查
    主从复制-常见问题
    redis-主从复制
    高级数据类型-GEO
    高级数据类型-HyperLogLog
    高级数据类型-bitmaps
    redis-redis.conf基础配置
    删除策略--逐出策略
    删除策略-过期数据
  • 原文地址:https://www.cnblogs.com/ListenFly/p/3335833.html
Copyright © 2011-2022 走看看