• 亨元模式 结构型模式之六


    1.定义

            享元模式是一种结构型设计模式, 它允许你在消耗少量内存的情况下支持大量对象。

    2.滑滑梯问题

            在说明亨元模式之前,我们先看看关于滑滑梯的程序设计。小区的楼下只有三个滑滑梯,但是想玩的小朋友却非常多。怎么设计计滑滑梯资源的管理,避免小朋友使用滑滑梯的时发生冲突呢。(这里我们设定每个滑滑梯每次仅能供一个小朋友玩耍)。解决这个问题,我们就可以使用享元模式(Flyweight),它就是运用共享技术有效的支持大量细粒度的对象

            怎么理解大量细粒度的对象呢?我一开始理解亨元模式的时候其实对这个概念理解的并不清楚。就滑滑梯这个问题,大家认为大量细粒度对象是滑滑梯还是小朋友呢?如果这个问题回答的不好,那么说明你对亨元模式还是不够了解。这里我直接给出答案,大量细粒度的对象指的是滑滑梯。有朋友会很疑惑,滑滑梯我们不是设定有三个么?怎么是大量细粒度对象,哪儿来的大量。其实这个问题逻辑很简单,我们假设有一百个小朋友要玩滑滑梯,那事实上我们只要造一百个滑滑梯就好了,对么。但现实是,我们并没有那么蠢,我们让小朋友排着队轮流玩就好了。三个滑滑梯事实上是果,是采用了亨元模式的果,已经是亨元模式优化过的情况。如果没有亨元模式,那么我们确实要造一百个滑滑梯,每个小朋友专属一个。

    3.实现思路

            如果不对滑滑梯的资源进行管理,可能会出现这个情况:小朋友们在使用滑滑梯时,并考虑当前滑滑梯是否被使用。很可能两个小朋友同时使用一个滑滑梯,导致冲突,不符合预期。所以我们重点是要对滑滑梯的资源使用进行有效的管理,比如这时候有一个大人来维护滑滑梯的使用秩序。大人作为三个滑滑梯的管理员,小朋友们使用滑滑梯需要向他提出申请,得到准许之后才能玩。经过大人管理之后的滑滑梯使用会变成这个情况:小朋友们排队申请滑滑梯的使用权限,大人根据滑滑梯的现有使用状况,如果还有滑滑梯上没有小朋友玩耍,那么可以提供该滑滑梯给小朋友,如果滑滑梯全部被使用则小朋友申请资源失败,需要继续等待。

            我们进一步假设,加入这时候小区其实存在若干个备用的充气滑滑梯,而且小区虽然有一百个小朋友,但他们并不是同时都在楼下玩的。这个时候整个系统就是一个动态的过程。只要有小朋友申请玩滑滑梯,管理员有限在现有的滑滑梯资源里找,如果有空闲的滑滑梯就会提供给当前申请的小朋友,如果没有那么就(新建资源)使用备用的充气滑滑梯。如果连备用的充气滑滑梯都用完了,这就已经触及到系统的资源上限了(内存上限),还是需要排队。

            总而言之,恒元模式就是解决需要为一个小朋友定制一个滑滑梯的问题。通过共享资源池来达到相同的目的。

    4.组成结构         

    1. 抽象享元:为具体享元角色规定了必须实现的方法,而外部状态就是以参数的形式通过此方法传入。(滑滑梯)
    2. 具体享元:实现抽象角色规定的方法。如果存在内部状态,就负责为内在部状态提供存储空间。(社区里具体的滑滑梯)
    3. 享元工厂角色:负责创建和管理享元角色。要想达到共享的目的,这个角色的实现是关键!(管理员)
    4. 客户端角色:维护对所有享元对象的引用,而且还需要存储对应的外部状态。 (小朋友)

    内部状态,就是各个对象不会随着环境的改变而改变的可共享部分;(滑梯本身)

    外部状态,指对象随环境改变而改变的不可以共享的部分。内部状态和外部状态彼此互不影响,改变其中一个并不会改变另一个的行为。(滑梯使用者)。

    享元模式将享元对象的状态外部化,而读取外部状态可能使得运行时间稍微变长。

    5.示例代码

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. //客户端类
    6. class Kid
    7. {
    8. private:
    9. string m_name;
    10. public:
    11. Kid(string name)
    12. {
    13. m_name = name;
    14. }
    15. std::string GetName()
    16. {
    17. return m_name;
    18. }
    19. };
    20. //抽象亨元类(滑滑梯)
    21. class Slide
    22. {
    23. public:
    24. virtual ~Slide() = default;
    25. virtual void Use(Kid user) = 0;
    26. };
    27. //具体亨元类(小区的滑滑梯)
    28. class ConcreteSlide :public Slide
    29. {
    30. private:
    31. string m_id;
    32. public:
    33. ConcreteSlide(std::string id)
    34. {
    35. m_id = id;
    36. }
    37. void Use(Kid user)override
    38. {
    39. cout << "滑滑梯:" << m_id << " 小朋友:" + user.GetName() << endl;
    40. }
    41. };
    42. //滑滑梯管理员
    43. //如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
    44. class SlideFactory
    45. {
    46. private:
    47. std::map flyweights;
    48. public:
    49. ~SlideFactory()
    50. {
    51. for (auto it = flyweights.begin(); it != flyweights.end(); ++it)
    52. delete it->second;
    53. }
    54. Slide* GetSlideCategory(string key)
    55. {
    56. for (auto it = flyweights.begin(); it != flyweights.end(); ++it)
    57. {
    58. if (it->first == key)
    59. return it->second;
    60. }
    61. Slide* slide = new ConcreteSlide(key);
    62. flyweights.insert(pair(key, slide));
    63. return slide;
    64. }
    65. int GetSlideCount()
    66. {
    67. return flyweights.size();
    68. }
    69. };
    70. int main()
    71. {
    72. SlideFactory f;
    73. Slide* fx = f.GetSlideCategory("一号滑梯");
    74. fx->Use(Kid("奇奇"));
    75. Slide* fy = f.GetSlideCategory("二号滑梯");
    76. fy->Use(Kid("天天"));
    77. Slide* fz = f.GetSlideCategory("三号滑梯");
    78. fz->Use(Kid("甜甜"));
    79. Slide* fl = f.GetSlideCategory("一号滑梯");
    80. fl->Use(Kid("嘟嘟"));
    81. Slide* fm = f.GetSlideCategory("二号滑梯");
    82. fm->Use(Kid("豆芽"));
    83. Slide* fn = f.GetSlideCategory("三号滑梯");
    84. fn->Use(Kid("年年"));
    85. cout << "得到滑滑梯总数:" << f.GetSlideCount() << endl;
    86. system("pause");
    87. return 0;
    88. }

    6.引用

    C++设计模式 - 享元模式 - 知乎 (zhihu.com)

    C++设计模式——享元模式 - 冰糖葫芦很乖 - 博客园 (cnblogs.com)

     

  • 相关阅读:
    Spring 中有哪些感知接口
    CSDN Meetup 回顾 丨从数据湖到指标中台,提升数据分析 ROI
    Target EDI 对接详解 – Partner Online EDI 注册
    基于verilog的CRC校验(汇总)
    uniapp报错:Cannot find module ‘@babel/parser‘
    skywalking集成nacos动态配置
    【华为OD机试真题 JAVA】学生方阵
    C语言程序设计——题目:输出特殊图案,请在c环境中运行,看一看,Very Beautiful!
    手把手教你实现一个JavaWeb项目:创建一个自己的网页博客系统(前端+后端)(一)
    有没有容易写的金融学论文选题?
  • 原文地址:https://blog.csdn.net/Physics_ITBoy/article/details/133385466