zoukankan      html  css  js  c++  java
  • 设计模式(15)---享元模式

    一、定义

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

    解释:需要大量重复new一个对象时,使用享元模式可以让你减少对象的初始化,从而减小内存开销。太苍白了,理解的不到位,希望自己以后补充吧。

    补充:当一个对象的状态可在外部初始化,同时系统中需要大量重复创建该对象时,享元模式在创建对象的工厂方法中使用一个哈希表,用于保存其外部化状态和对象本身。在系统中,使用对象时首先判断其是否存在,存在则拿来直接使用,不存在需要重新创建并保存到哈希表中。

    二、UML类图及基本代码

    基本代码:

    public abstract class Flyweight
        {
            public abstract void Operation(int extrinsicstate);
        }
    
        public class ConcreteFlyweight : Flyweight
        {
            // 内部状态
            private string intrinsicstate;
    
            // 构造函数
            public ConcreteFlyweight(string innerState)
            {
                this.intrinsicstate = innerState;
            }
    
            /// <summary>
            /// 享元类的实例方法
            /// </summary>
            /// <param name="extrinsicstate">外部状态</param>
            public override void Operation(int extrinsicstate)
            {
                Console.WriteLine("具体实现类: intrinsicstate {0}, extrinsicstate {1}", intrinsicstate, extrinsicstate);
            }
        }
    
    public class FlyweightFactory
        {
            // 最好使用泛型Dictionary<string,Flyweighy>
            //public Dictionary<string, Flyweight> flyweights = new Dictionary<string, Flyweight>();
            public Hashtable flyweights = new Hashtable();
    
            public FlyweightFactory()
            {
                flyweights.Add("A", new ConcreteFlyweight("A"));
                flyweights.Add("B", new ConcreteFlyweight("B"));
                flyweights.Add("C", new ConcreteFlyweight("C"));
            }
    
            public Flyweight GetFlyweight(string key)
            {
                // 更好的实现如下
                //Flyweight flyweight = flyweights[key] as Flyweight;
                //if (flyweight == null)
                //{
                // Console.WriteLine("驻留池中不存在字符串" + key);
                // flyweight = new ConcreteFlyweight(key);
                //}
                //return flyweight;
    
                return flyweights[key] as Flyweight;
            }
        }

    客户端调用:

    class Program
        {
            static void Main(string[] args)
            {
                // 定义外部状态,例如字母的位置等信息
                int externalstate = 10;
                // 初始化享元工厂
                FlyweightFactory factory = new FlyweightFactory();
    
                // 判断是否已经创建了字母A,如果已经创建就直接使用创建的对象A
                Flyweight fa = factory.GetFlyweight("A");
                if (fa != null)
                {
                    // 把外部状态作为享元对象的方法调用参数
                    fa.Operation(--externalstate);
                }
                // 判断是否已经创建了字母B
                Flyweight fb = factory.GetFlyweight("B");
                if (fb != null)
                {
                    fb.Operation(--externalstate);
                }
    
                // 判断是否已经创建了字母D
                Flyweight fd = factory.GetFlyweight("D");
                if (fd != null)
                {
                    fd.Operation(--externalstate);
                }
                else
                {
                    Console.WriteLine("驻留池中不存在字符串D");
                    // 这时候就需要创建一个对象并放入驻留池中
                    ConcreteFlyweight d = new ConcreteFlyweight("D");
                    factory.flyweights.Add("D", d);
                }
    
                Console.Read();
            }
        }
    View Code

    运行结果:

    三、具体实例:

    构建一个由不同用户使用的通用网站,具体代码如下:

    public class User
        {
            private string name;
            public string Name
            {
                get { return name; }
            }
    
            public User(string name)
            {
                this.name = 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)
            {
                Console.WriteLine("website type:" + name + "user:" + 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;
            }
        }

    客户端调用:

    WebsiteFactory wf = new WebsiteFactory();
    
                Website wx = wf.GetWebsiteCategory("show");
                wx.Use(new User("a"));
    
                Website wy = wf.GetWebsiteCategory("show");
                wy.Use(new User("b"));
    
                Website wz = wf.GetWebsiteCategory("see");
                wz.Use(new User("c"));
    
                Console.WriteLine("website type num:" + wf.GetWebsiteCount());
    View Code

    四、优缺点及适用场景

    优点:

    降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。

    缺点:

    1)为了使对象可以共享,需要将对象的一些状态外部化,增加了系统复杂度

    2)将享元对象状态外部化,使得读取外部状态的运行时间稍微变长。

    适用场景:

    系统中需要大量的细粒度对象,同时这些对象耗费大量的内存,并且对象的状态大部分可以外部化,此时使用享元模式是没有错的。

  • 相关阅读:
    StarRTC , AndroidThings , 树莓派小车,公网环境,视频遥控(二)小车端
    StarRTC , AndroidThings , 树莓派小车,公网环境,视频遥控(一)准备工作
    公司名称后缀 Inc. Co.,Ltd.
    Linux C定时器使用指南
    配置QQ企业邮箱小结
    常用PHP文件操作函数
    Git基本命令 -- 基本工作流程 + 文件相关操作
    Git基本命令 -- 创建Git项目
    Entity Framework Core 2.0 入门
    用VSCode开发一个asp.net core2.0+angular5项目(5): Angular5+asp.net core 2.0 web api文件上传
  • 原文地址:https://www.cnblogs.com/ysyn/p/4146090.html
Copyright © 2011-2022 走看看