当前位置: 首页 > news >正文

亨元模式 结构型模式之六

1.定义

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

2.滑滑梯问题

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

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

3.实现思路

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

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

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

4.组成结构         

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

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

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

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

5.示例代码

#include <iostream>
#include<string>
#include<map>
using namespace std;//客户端类
class Kid
{
private:string m_name;
public:Kid(string name){m_name = name;}std::string GetName(){return m_name;}
};//抽象亨元类(滑滑梯)
class Slide
{
public:virtual ~Slide() = default;virtual void Use(Kid user) = 0;
};//具体亨元类(小区的滑滑梯)
class ConcreteSlide :public Slide
{
private:string m_id;
public:ConcreteSlide(std::string id){m_id = id;}void Use(Kid user)override{cout << "滑滑梯:" << m_id << "  小朋友:" + user.GetName() << endl;}
};//滑滑梯管理员
//如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
class SlideFactory
{
private:std::map<std::string, Slide*> flyweights;
public:~SlideFactory(){for (auto it = flyweights.begin(); it != flyweights.end(); ++it)delete it->second;}Slide* GetSlideCategory(string key){for (auto it = flyweights.begin(); it != flyweights.end(); ++it){if (it->first == key)return it->second;}Slide* slide = new ConcreteSlide(key);flyweights.insert(pair<std::string, Slide*>(key, slide));return slide;}int GetSlideCount(){return flyweights.size();}
};int main()
{SlideFactory f;Slide* fx = f.GetSlideCategory("一号滑梯");fx->Use(Kid("奇奇"));Slide* fy = f.GetSlideCategory("二号滑梯");fy->Use(Kid("天天"));Slide* fz = f.GetSlideCategory("三号滑梯");fz->Use(Kid("甜甜"));Slide* fl = f.GetSlideCategory("一号滑梯");fl->Use(Kid("嘟嘟"));Slide* fm = f.GetSlideCategory("二号滑梯");fm->Use(Kid("豆芽"));Slide* fn = f.GetSlideCategory("三号滑梯");fn->Use(Kid("年年"));cout << "得到滑滑梯总数:" << f.GetSlideCount() << endl;system("pause");return 0;
}

6.引用

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

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

http://www.lryc.cn/news/182787.html

相关文章:

  • 面试题: Spring中Bean的实例化和Bean的初始化有什么区别?
  • 阻塞队列,生产者消费者模型
  • 【RCRL充放电时间相关计算】
  • C++ primer plus--输入、输出和文件
  • 案例题--Web应用考点
  • MySQL的SQL 优化:提升数据库性能
  • 【匠心打造】从0打造uniapp 可视化拖拽设计 c_o 第十篇
  • BIT-5-操作符详解(C语言初阶学习)
  • 【重拾C语言】三、分支程序设计(双分支和单分支程序设计、逻辑判断、多分支程序设计、枚举类型表示;典型例题:判断闰年和求一元二次方程根)
  • Shiro应用到Web Application
  • 【POST请求-腾讯翻译君-爬虫案例】
  • 多卡片效果悬停效果
  • 首饰饰品经营商城小程序的作用是什么
  • 华为OD机试真题【服务器能耗统计】
  • ubuntu按下del却出现空格(命令行下键盘错乱)
  • Go开始:Go基本元素介绍
  • 十二、【漏洞复现】Rails任意文件读取(CVE-2019-5418)
  • 【计算机视觉|人脸建模】学习从4D扫描中获取的面部形状和表情的模型
  • 【ADB】蓝牙总结
  • 嵌入式系统设计与应用---ARM处理器体系结构(学习笔记)
  • 计算机竞赛 身份证识别系统 - 图像识别 深度学习
  • StarRocks数据导入
  • JavaSE | 初识Java(一) | JDK \ JRE \ JVM
  • 6轮面试阿里Android开发offer,薪资却从21k降到17k,在逗我?
  • 基于混合蛙跳优化的BP神经网络(分类应用) - 附代码
  • [架构之路-230]:计算机硬件与体系结构 - 可靠性、可用性、稳定性;MTTF、MTTR、MTBF
  • selenium自动化测试环境安装教程
  • 如何修改springboot项目启动时的默认图标?
  • 基于阴阳对优化的BP神经网络(分类应用) - 附代码
  • Spring bean定义Spring Bean 的作用域