秒懂设计模式--学习笔记(11)【结构型-享元模式】

目录

      • 10、享元模式
        • 10.1 享元模式
        • 10.2 举例
          • 10.2.1 马赛克
          • 10.2.2 游戏地图(以草原地图作为范例)
        • 10.3 总结

10、享元模式

10.1 享元模式
  • “享元”则是共享元件的意思
  • 享元模式的英文flyweight是轻量级的意思,这就意味着享元模式能使程序变得更加轻量化
  • 当系统存在大量的对象,并且这些对象又具有相同的内部状态时,我们就可以用享元模式共享相同的元件对象,以避免对象泛滥造成资源浪费。
  • 测试类结构
    享元模式测试类结构
10.2 举例
10.2.1 马赛克
  • 虽然马赛克小块数量比较多,但经过观察我们会发现,
  • 分析组成,进行归类后,找到元件只有4种:黑色块、灰色块、灰白色块以及白色块。
  • 我们可以说,这就是4个“元”色块
10.2.2 游戏地图(以草原地图作为范例)
  • 对组成部分进行归类分析,找到原件
    • 游戏地图都是由一个个小的单元图块组成的
    • 其中除房屋比较大之外,其他图块的尺寸都一样,它们分别为河流、草地、道路,这些图块便是4个元图块
  • 分析建模
    • 定义一个图块类来描述图块,具体属性应该包括“图片”和“位置”信息,并且具备按照这些信息去绘制图块的能力:Segment
    package flyweight;/*** @Description 图块类*/
    public class Segment {/*** 材质图*/private String image;/*** 位置坐标*/private int x,y;/*** 显式带参构造方法:初始化各参数* @param image 材质图* @param x 横坐标* @param y 纵坐标*/public Segment(String image, int x, int y) {this.image = image;System.out.println("从磁盘加载[" + image + "]图片……");this.x = x;this.y = y;}/*** 图块绘制方法:按坐标位置绘制在地图上*/public void draw() {System.out.println("在位置[" + x + ":" + y + "]上绘制图片:[" + image + "]");}
    }
    
    • 在地图第一行随便绘制一些图块,Client.test1()
      • 在这一步会发现,图片加载很慢,一张图片加载要半秒,10张图块就要耗费5秒,影响用户体验
    package flyweight;/**
    *@Description 测试类
    */
    public class Client {private static void test1() {//在地图第一行随便绘制一些图块new Segment("河流", 10, 10).draw();new Segment("河流", 10, 20).draw();new Segment("道路", 10, 30).draw();new Segment("草地", 10, 40).draw();new Segment("草地", 10, 50).draw();new Segment("草地", 10, 60).draw();new Segment("草地", 10, 70).draw();new Segment("草地", 10, 80).draw();new Segment("道路", 10, 90).draw();new Segment("道路", 10, 100).draw();}
    }
    
    • 图片与坐标状态初始化后就固定下来了,简单讲就是被绘制出来后就不必变动了,即使要变也是将拼好的地图作为一个大对象整体挪动
  • 图件共享(优化)
    • 继续分析每个图块的坐标是不同的,但有很大一部分图块的材质图(图片)是相同
    • 于是我们可以得出结论,材质图是可以作为享元的,而坐标则不能
    • 既然要共享相同的图片,那么我们就得将图块类按图片拆分成更细的材质类,如河流类、草地类、道路类等
    • 而坐标不能作为图块类的享元属性,所以我们就得设法把这个属性抽离出去由外部负责
    • 代码实战
      • 首先需要定义一个接口,规范这些材质类的绘图标准(接口:规范标准Drawable)
        • 当然,除了接口方式,我们还可以用抽象类抽离出更多的属性和方法,使子类变得更加简单
    package flyweight;
    /**
    * @Description 绘图接口: 规范这些材质类的绘图标准
    *                  当然,除了接口方式,我们还可以用抽象类抽离出更多的属性和方法,使子类变得更加简单
    */
    public interface DrawAble {
    /**
    * 绘图方法,接收地图坐标
    * @param x 横坐标
    * @param y 纵坐标
    */
    void draw(int x, int y);
    }
    
    • 定义一系列材质类并实现此绘图接口
      • 河流类River
      package flyweight.texture;
      import flyweight.DrawAble;
      /*** @Description 河流类*/
      public class River implements DrawAble {/*** 享元属性: 河流图片材质作为内部属性*/private String image;/*** 类构造器中加载河流图片*      这就是类内部即将共享的“元”数据了,我们通常称之为“内蕴状态”*/public River() {this.image = "河流";System.out.print("从磁盘加载[" + image + "]图片,耗时……");}/*** 重写绘图方法* 而作为“外蕴状态”的坐标是无法作为享元的,由外部传入* @param x 横坐标* @param y 纵坐标*/@Overridepublic void draw(int x, int y) {System.out.println("在位置[" + x + ":" + y + "]上绘制图片:[" + image + "]");}
      }
      
      • 草地类Grass
       package flyweight.texture;import flyweight.DrawAble;/*** @Description 草地类*/public class Grass implements DrawAble {/*** 享元属性:草地图片材质*/private String image;public Grass() {this.image = "草地";System.out.print("从磁盘加载[" + image + "]图片,耗时……");}@Overridepublic void draw(int x, int y) {System.out.println("在位置[" + x + ":" + y + "]上绘制图片:[" + image + "]");}}
      
      • 道路类Road
      	package flyweight.texture;import flyweight.DrawAble;/*** @Description 道路类*/public class Road implements DrawAble {/*** 道路图片材质*/private String image;public Road() {this.image = "道路";System.out.println("从磁盘加载[" + image + "]图片,耗时…");}@Overridepublic void draw(int x, int y) {System.out.println("在位置[" + x + ":" + y + "]上绘制图片:[" + image + "]");}}
      
      • 房屋类House
       package flyweight.texture;import flyweight.DrawAble;/*** @Description 房屋类*/public class House implements DrawAble {private String image;//房屋图片材质public House() {this.image = "房屋";System.out.print("从磁盘加载[" + image + "]图片,耗时……");}@Overridepublic void draw(int x, int y) {System.out.print("将图层切换到顶层……");//房屋盖在地板上,所以切换到顶层图层System.out.println("在位置[" + x + ":" + y + "]上绘制图片:[" + image + "]");}}
      
    • “元之共享”的关键:
      • 定义一个图件工厂类
       package flyweight.factory;import flyweight.DrawAble;import flyweight.texture.Grass;import flyweight.texture.House;import flyweight.texture.River;import flyweight.texture.Road;import java.util.HashMap;import java.util.Map;/*** @Description 图件工厂类*/public class SegmentFactory {/*** 图库: 维护着所有的图件元对象*/private Map<String, DrawAble> images;public SegmentFactory() {images = new HashMap<String, DrawAble>();}public DrawAble getDrawable(String image) {//缓存池里如果没有图件,则实例化并放入缓存池if(!images.containsKey(image)){switch (image) {case "河流":images.put(image, new River());break;case "草地":images.put(image, new Grass());break;case "道路":images.put(image, new Road());break;case "房屋":images.put(image, new House());}}//至此,缓存池里必然有图件,直接取得并返回return images.get(image);}}
      
      • 并将各种图件对象提前放入内存中共享,如此便可以避免每次从磁盘重新加载
    • 测试:Client.test2()
          private static void test2() {//先实例化图件工厂SegmentFactory factory = new SegmentFactory();/** 随便绘制一列为例:*      抛弃了利用“new”关键字随意制造对象的方法,*      改用这个图件工厂类来构建并共享图件元,外部需要什么图件直接向图件工厂索要即可*/factory.getDrawable("河流").draw(10, 10);factory.getDrawable("河流").draw(10, 20);factory.getDrawable("道路").draw(10, 30);factory.getDrawable("草地").draw(10, 40);factory.getDrawable("草地").draw(10, 50);factory.getDrawable("草地").draw(10, 60);factory.getDrawable("草地").draw(10, 70);factory.getDrawable("草地").draw(10, 80);factory.getDrawable("道路").draw(10, 90);factory.getDrawable("道路").draw(10, 100);//绘制完地板后接着在顶层绘制房屋factory.getDrawable("房子").draw(10, 10);factory.getDrawable("房子").draw(10, 50);}
      
    • 小结
      • 相同部分可以作为享元,如在构造器中加载的,作为内部类即将共享的元数据,通常称为“内蕴状态”
      • 不同部分不能作为享元,如在实现房中作为参数传入的属性,称为“外蕴状态”
10.3 总结
  • 享元模式让图件对象将可共享的内蕴状态“图片”维护起来,将外蕴状态“坐标”抽离出去并定义于接口参数中
  • 基于此,享元工厂便可以顺利将图件对象共享,以供外部随时使用。
  • 享元模式的各角色定义如下
    • Flyweight(享元接口):所有元件的高层规范,声明与外蕴状态互动的接口标准。如:DrawAble。
    • ConcreteFlyweight(享元实现):
      • 享元接口的元件实现类,自身维护着内蕴状态,且能接受并响应外蕴状态,
      • 可以有多个实现。如:河流类River、草地类Grass、道路类Road等。
      • 一个享元对象可以被称作一个“元”
    • FlyweightFactory(享元工厂):用来维护享元对象的工厂,负责对享元对象实例进行创建与管理,并对外提供获取享元对象的服务。SegmentFactory
    • Client(客户端):享元的使用者,负责维护外蕴状态。Client
  • “享元”的理念其实就是萃取事物的本质
  • 将对象的内蕴状态与外蕴状态剥离开来,其中内蕴状态成为真正的“元”数据,而外蕴状态则被抽离出去由外部负责维护

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/48092.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

stack(leetcode练习题)

文章目录 STL用法总结32 最长有效括号思路代码 496 下一个最大元素思路代码 856 括号的分数思路 STL用法总结 关于stack的知识&#xff0c;可以看点击查看上面的博客&#xff0c;以下题目全在leetcode 32 最长有效括号 思路 “(()” “()(()” “(()(((()” 最开始写的&…

Linux下docker快速安装gitea

之前在服务器上装的gitlab来管理个人项目&#xff0c;但是gitlab服务启动后能明显感受到占用资源比较严重。最近服务器到期&#xff0c;换了个服务器还没来得及装gitlab&#xff0c;刚好最近接触到gitea&#xff0c;网上是这么说的 占用资源少&#xff0c;适合个人开发者&…

[PM]数据分析

概览 数据的定义 运营数据 分析的目的 数据分析流程 1.明确目标 2.数据来源 3.采集数据 4.数据整理 5.数据分析 趋势分析 当数据出现异常&#xff0c;一般从3个角度去查找问题&#xff1a; 1.技术层面&#xff0c;是不统计出错&#xff0c;或者产品出现bug 工 2.产品层面&am…

连接hive库增加相关包

连接hive库增加相关包 例如&#xff1a;java.lang.NoClassDefFoundError: com/ctc/wstx/io/InputBootstrapper org.apache.hadoop.hive.common.auth.HiveAuthUtils java.lang.NoClassDefFoundError: org/codehaus/stax2/XMLInputFactory2

0711springNews新闻系统管理 实现多级评论

0611springmvc新闻系统管理-CSDN博客 0711springNews新闻系统管理项目包 实现多级评论-CSDN博客 数据库字段 需要添加父节点id&#xff0c;通过该字段实现父评论和子评论的关联关系。 对象属性 实现链表&#xff0c;通过一个父评论可以找到它对应的所有子孙评论。 业务层 实现…

Capture软件元件库(以STM32为例)

本教程基于【凡亿】Cadence Allegro 17.4零基础入门66讲PCB Layout设计实战视频 &#xff08;一&#xff09;自带库路径查找 1&#xff0c;首先在找到文件的快捷方式 2&#xff0c;右键打开文件所在位置 3&#xff0c;点击tools&#xff08;上一级目录&#xff09; 4&#xf…

数据库最佳实践:优化爬虫管理的数据存储方案

摘要&#xff1a; 面对日益增长的数据抓取需求&#xff0c;如何高效管理和存储爬虫获取的海量信息成为一大挑战。本文将深入探讨数据库最佳实践&#xff0c;揭示如何通过优化策略提升爬虫数据存储效率&#xff0c;助您跨越数据管理的障碍&#xff0c;实现数据价值最大化。 一、…

SpringBoot+Vue(3)Excel的在线预览

一、思路 在Spring Boot和Vue.js的组合中实现Excel文件的在线预览功能&#xff0c;通常涉及到几个关键步骤&#xff1a;文件上传、文件存储、文件读取、以及通过前端展示Excel内容。由于Excel文件本身不是直接可以在网页上渲染的格式&#xff0c;我们通常需要将Excel文件转换为…

SpringMVC源码深度解析(下)

接着上一遍博客《SpringMVC源码深度解析(中)》继续聊。上一篇博客中&#xff0c;返回的是对象的情况下SpringMVC框架会怎么处理&#xff0c;这种情况也是现在用得最多的&#xff0c;因为都是前后端分离。如果返回的是ModelAndView&#xff0c;则是另外的处理逻辑了&#xff0c;…

稀疏支持向量机(Sparse Support Vector Machine, Sparse SVM)

稀疏支持向量机&#xff08;Sparse Support Vector Machine, Sparse SVM&#xff09; 稀疏支持向量机是一种在支持向量机的基础上&#xff0c;通过引入稀疏性约束&#xff0c;使得模型参数更加稀疏&#xff0c;从而提高模型的可解释性和计算效率的方法。以下是稀疏支持向量机的…

Ideal窗口中左右侧栏消失了

不知道大家在工作过程中有没有遇到过此类问题&#xff0c;不论是Maven项目还是Gradle项目&#xff0c;突然发现Ideal窗口右侧图标丢失了&#xff0c;同事今天突然说大象图标不见了&#xff0c;不知道怎样刷新gradle。 不要慌张&#xff0c;下面提供一些解决思路&#xff1a; 1…

LeetCode 232.用栈实现队列 C写法

LeetCode 232.用栈实现队列 C写法 思路&#x1f9d0;&#xff1a; 栈代码在本篇中。与队列实现栈类似&#xff0c;不过这里我们建立两个栈&#xff0c;一个栈专门存放入队数据&#xff0c;一个专门存放出队数据&#xff0c;不需要再来回导数据。原理在于一个栈的数据到另一个栈…

Windows右键新建Markdown文件类型配置 | Typora | VSCode

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 今天毛毛张分享的是如何在右键的新建菜单中添加新建MarkdownFile文件&#xff0c;这是毛毛张分享的关于Typora软件的相关知识的第三期 文章目录 1.前言&#x1f3dd;…

「MQTT over QUIC」与「MQTT over TCP」与 「TCP 」通信测试报告

一、结论 在实车5G测试中「MQTT Over QUIC」整体表现优于「TCP」&#xff0c;可在系统架构升级时采用MQTT Over QUIC替换原有的TCP通讯&#xff1b;从实现原理上基于QUIC比基于TCP在弱网、网络抖动导致频繁重连场景延迟更低。 二、测试方案 网络类型&#xff1a;实车5G、实车…

Easysearch、Elasticsearch、Amazon OpenSearch 快照兼容对比

启动集群 Easysearch sysctl -w vm.max_map_count262144Amazon OpenSearch Elasticsearch 由于这个docker compose没有关于kibana的配置&#xff0c;所以我们还是用Console添加原生的Elasticsearch集群 集群信息 快照还原的步骤 快照前的准备 插件安装 本次测试选择把索…

生产力工具|Endnote 21 Macwin版本安装

一、软件下载&#xff1a; &#xff08;一&#xff09;mac版本 Endnote 21版本下载&#xff1a;点击下载 Endnote 20版本下载&#xff1a;点击下载 Endnote X9版本下载&#xff1a;点击下载 &#xff08;二&#xff09;Endnote 20 Win版本 第一步&#xff1a;安装好官网软…

【技术前沿 | AI Native应用新纪元:深度解析模型微调的艺术】

在这个智能化浪潮席卷全球的今天&#xff0c;AI技术已经不再是遥不可及的未来概念&#xff0c;而是深深地融入了我们的日常生活与工作中。从智能家居到自动驾驶&#xff0c;从智能客服到医疗诊断&#xff0c;AI正以它独有的方式改变着世界。而在这一过程中&#xff0c;AI Nativ…

随手记:推荐vscode好用的几个小插件

原始用了挺久的插件&#xff0c;先上截图&#xff0c;以后有空再编辑&#xff1a; fittenCode 是一个AI小助手&#xff0c;相对来说很智能&#xff0c;你在vscode当中编写代码&#xff0c;甚至都可以知道你下一步知道干嘛&#xff0c;训练的还可以。而且还可以帮你起名字&…

2024年7月17日(nodejs,npm设置国内镜像,vue脚手架,远程管理ssh,踢出用户,scp命令,ssh免密登录)

1、安装nodejs服务 nodejs是一个运行1环境&#xff0c;和javajdk运行环境格式一样 [roota ~]# yum -y install nodejs.x86_64 安装完成之后&#xff0c;使用node -v 查看版本 [roota ~]# node -v v16.20.2 2、简易服务器的环境安装npm 安装包管理器 npm node packae manger [ro…

云计算实训09——rsync远程同步、自动化推取文件、对rsyncd服务进行加密操作、远程监控脚本

一、rsync远程同步 1.rsync基本概述 &#xff08;1&#xff09;sync同步 &#xff08;2&#xff09;async异步 &#xff08;3&#xff09;rsync远程同步 2.rsync的特点 可以镜像保存整个目录树和文件系统 可以保留原有权限&#xff0c;owner,group,时间&#xff0c;软硬链…