设计模式之------享元模式(Flyweight Pattern):内部状态(Instrinsic State)\外部状态(Extrinsic State)

一、概念

①、什么是享元模式?

       运用共享技术有效地支持大量细粒度的对象。

②、什么是细粒度对象?享元模式的两个状态?

       在分析什么是细粒度对象之前,我们现了解一下享元对象的两个状态:内部状态和外部状态。

       在享元对象内部并且不用随环境改变而改变的共享部分,成为享元对象的内部状态,而随环境改变而改变的、不可以共享的状态就是外部状态。内部状态存储于ConcreteFlyweight对象之中,而外部对象则应该考虑由客户端对象存储或计算。当调用Flyweight对象的操作时,将该状态传递给它。

        在实际使用中,能够共享的内部状态是有限的,因此享元对象一般都设计为较小的对象,它所包含的内部状态较少,这种对象也成为细粒度对象。

③、解决什么问题(出现的背景)?

       面向对象技术可以很好的解决一写灵活性或扩展性问题,但在很多情况下需要在系统中增加类和对象的个数。当对象数量太多时,将导致运行代价过高,带来性能下降,内存溢出等问题。为了解决这一问题便诞生了享元模式。把其中具有相同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。

④、如何解决?

       用唯一标识码(key)判断,如果内存中有,则返回这个唯一标识码所标识的对象。

⑤、何时使用?

        系统有大量相似的对象;需要缓冲池的场景。

⑥、享元模式的核心是什么?

       享元模式的核心在于享元工厂类,享元工厂类的作用在于提供一个用于存储享元对象的享元池,用户需要对象时,首先从享元池中获取,如果享元池不存在,则创建一个新的享元对象返回给用户,并在享元池中保存新增对象。

⑦、享元模式优缺点?

       优点:大大较少对象的创建,降低系统的内存,使效率提高。

       缺点:提高了系统的复杂度,需要分类出外部状态和内容状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。

二、图

①、结构图

②、拓展图

        公用一个Hello World!对象,其中字符串“Hello World!”为内部状态,可共享;字体颜色为外部状态,不可共享,由客户端设定。即内部状态存储与享元对象内部,而外部状态则有客户端来考虑设定。

三、代码

①、代码类图

②、代码

客户端类

 //客户端类
        static void Main(string[] args)
        {
            WebSiteFactory f = new WebSiteFactory();                     //创建一个享元池:实例化一个网络工厂类,对象f以哈希表的方式存储

            WebSite fx = f.GetWebSiteCateGory("产品展示");               //建立一个网站fx对象:调取f对象的GetWebiteCateGory方法,获取网站类型,并将其赋值给fx
            fx.use(new User("路飞"));                                    //调用网站的use方法,并将外部状态用户添加至显示信息里

            WebSite fy = f.GetWebSiteCateGory("产品展示");               //创建一个类型为产品展示的网站,因享元池内已有实例,所以不用再次创建,直接共享即可
            fy.use(new User("索隆"));

            WebSite fz = f.GetWebSiteCateGory("产品展示");               //共享享元池内的“产品展示”
            fz.use(new User("山治"));

            WebSite fl = f.GetWebSiteCateGory("博客");                   //在享元池内实例化一个博客类型的网站。
            fl.use(new User("布鲁克"));

            WebSite fm = f.GetWebSiteCateGory("博客");
            fm.use(new User("弗兰奇"));

            WebSite fn = f.GetWebSiteCateGory("博客");
            fn.use(new User("乔巴"));

            Console.WriteLine("网站分类总数为{0}",f.GetWebSiteCount());   //获取不同类型的网站数量
            Console.Read();
        }

用户类

//用户类
    public class User
    {
        private string name;
        public User (string name)                                        //创建User构造函数,获取用户名
        {
            this.name = name;
        }
        public string Name      
        {
            get { return name; }
        }
  
    }

网站抽象类

 //网站抽象类
    abstract class WebSite                                               //创建一个抽象的网站类
    {
        public abstract void use(User user);                             //创建一个抽象的网站使用方法,参数为用户
    }

具体网站类

//具体网站类
    class ConcreteWebSite:WebSite                                        //创建一个具体的网站类
    {
        private string name = "";                                        //声明一个name变量,并赋予初始值
        public ConcreteWebSite(string name)                              //为此类创建构造函数,参数为网站名称
        {
            this.name = name;
        }
        public override void use(User user)                              //传递的不再是之前的已有的整数类,而是我们自定义的User类,user是对象,而非向整数类中一个具体的数字,需要调取属性使用
        {
            Console.WriteLine("网站分类:"+name+"    用户:{0}",user.Name);
        }
    }

网站工厂类

//网站工厂类
    class WebSiteFactory
    {
        private Hashtable flyweights = new Hashtable();                  //创建一个享元池(空的):私有的哈希表类,名称为flyweights
        public WebSite  GetWebSiteCateGory(string key)                   //创建一个WebSite类型返回值GetWebSiteCateGory()方法获取网站类型
        {                                                                //判断享元池中是否包含此类型
            if (!flyweights.ContainsKey(key))                            //如果不包含
                flyweights.Add(key, new ConcreteWebSite(key));           //则创建对象,并将其添加至享元池
            return ((WebSite)flyweights[key]);                           //如果包含则直接返回对象
        }
        public int GetWebSiteCount()                                     //创建一个返回值为int类型的GetWebSiteCount()方法
        {
            return flyweights.Count;                                     //返回哈希表中的数量
        }
    }

四、拓展

https://blog.csdn.net/justloveyou_/article/details/55045638

https://blog.csdn.net/z_s_z2016/article/details/80977073

 以上便是享元模式的简单梳理,下一站走起^_^

猜你喜欢

转载自blog.csdn.net/Elsa15/article/details/87930541
今日推荐