• 设计模式---享元模式


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

    享元模式:

    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
    }

    测试结果:

  • 相关阅读:
    jar包的MANIFEST.MF文件
    Spring AOP无法拦截Controller中的方法
    强制更新 Maven缓存库
    【转】深入理解Java:注解(Annotation)--注解处理器
    Java-Method类常用方法详解
    MySQL下查看用户和建立用户
    【转】从零开始玩转logback
    【转】Java日志框架:logback详解
    【转】配置不当引起高危漏洞?看加密货币交易所如何正确用Spring Boot Actuaotr框架
    Spring MVC Junit4 单元測试 JunitTest
  • 原文地址:https://www.cnblogs.com/fblogs/p/12313751.html
Copyright © 2020-2023  润新知