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

    享元模式:解决对象的复用问题,提供第三方的管理,不破坏类的封装
          自行实例化对象,不像单例时强制保证
    池化资源管理:
      享元工厂也可以初始化多个对象---其他地方需要使用对象可以找工厂拿(修改个状态)--用完之后在放回来(状态修改回来)
      避免重复的创建和销毁资源(特别是对于非托管资源,像:数据库连接,线程)

    享元模式:

    1.实现一:

    public class FlyweightFactory
    {
    private static Dictionary<WordType, BaseWorld> FlyweightFactoryDictionary = new Dictionary<WordType, BaseWorld>();

    /// <summary>
    /// 1.如果是5个线程同时调用,字典为空,所以会同时构造5次E
    /// 2.最后只只打印一个ELEVEN,因为其他线程都挂掉了,因为在字典中添加相同的值的时候,挂掉了
    /// 3. 2个L是小概率事件,前两个线程是同时添加E,所以没有失败,所以L有两个,但是到L的时候又冲突了
    /// 4.子线程的异常时看不到的,除非waitall
    /// </summary>
    /// <param name="wordType"></param>
    /// <returns></returns>
    public static BaseWorld CreateWord(WordType wordType)
    {
    if (!FlyweightFactoryDictionary.ContainsKey(wordType))
    {
    BaseWorld word = null;
    switch (wordType)
    {
    case WordType.E:
    word = new E();
    break;
    case WordType.L:
    word = new L();
    break;
    case WordType.V:
    word = new V();
    break;
    case WordType.N:
    word = new N();
    break;
    default:
    throw new Exception();
    }
    FlyweightFactoryDictionary.Add(wordType, word);
    }

    return FlyweightFactoryDictionary[wordType];
    }
    }

    public enum WordType
    {
    E,
    L,
    V,
    N
    }

    测试代码:

    for (int i = 0; i < 5; i++)
    {
    Task.Run(() =>
    {
    BaseWorld e = FlyweightFactory.CreateWord(WordType.E);
    BaseWorld l = FlyweightFactory.CreateWord(WordType.L);
    BaseWorld V = FlyweightFactory.CreateWord(WordType.V);
    BaseWorld n = FlyweightFactory.CreateWord(WordType.N);
    Console.WriteLine("{0}{1}{2}{3}{4}{5}", e.Get(), l.Get(), e.Get(), V.Get(), e.Get(), n.Get());
    });
    }

    测试结果:

    2.实现方式二:

    public class FlyweightFactory
    {
    private static Dictionary<WordType, BaseWorld> FlyweightFactoryDictionary = new Dictionary<WordType, BaseWorld>();

    /// <summary>
    /// 不想看到多线程的时候生成多个E,加锁
    /// </summary>
    private readonly static object FlyweightFactoryLock = new object();

    /// <summary>
    /// 1.如果是5个线程同时调用,字典为空,所以会同时构造5次E
    /// 2.最后只只打印一个ELEVEN,因为其他线程都挂掉了,因为在字典中添加相同的值的时候,挂掉了
    /// 3. 2个L是小概率事件,前两个线程是同时添加E,所以没有失败,所以L有两个,但是到L的时候又冲突了
    /// 4.子线程的异常时看不到的,除非waitall
    /// </summary>
    /// <param name="wordType"></param>
    /// <returns></returns>
    public static BaseWorld CreateWord(WordType wordType)
    {
    if (!FlyweightFactoryDictionary.ContainsKey(wordType))
    //是为了性能优化,避免对象已经被初始化后,再次请求还需要等待锁
    {
    lock (FlyweightFactoryLock)//相当于Monitor.Enter, 保证方法体只有一个线程可以进入
    {
    if (!FlyweightFactoryDictionary.ContainsKey(wordType))
    {
    BaseWorld word = null;
    switch (wordType)
    {
    case WordType.E:
    word = new E();
    break;
    case WordType.L:
    word = new L();
    break;
    case WordType.V:
    word = new V();
    break;
    case WordType.N:
    word = new N();
    break;
    default:
    throw new Exception();
    }
    FlyweightFactoryDictionary.Add(wordType, word);
    }
    }
    }

    return FlyweightFactoryDictionary[wordType];
    }
    }

    public enum WordType
    {
    E,
    L,
    V,
    N
    }

    测试结果:

  • 相关阅读:
    ios程序中传值的几种方式
    iOS系统、设备信息获取方式
    关于如何使自定义的Button和系统的UIBarButtonItem保持一致的两种方法
    关于iOS中音视频播放的几种方式介绍
    关于IOS数据操作方式详解(三)— Sqlite数据解析
    关于iOS数据操作方式详解(二)— Jason数据解析
    关于IOS数据操作方式详解(一)— XML数据解析
    git常用命令
    pip及npm换源
    win10安装Docker并换国内源
  • 原文地址:https://www.cnblogs.com/fblogs/p/12313751.html
Copyright © 2011-2022 走看看