设计模式之(11)——享元模式

继续把我们的设计模式捡起,希望我能坚持完这个系列吧,下面我们就进入正题吧。

在软件开发过程中,我们需要重复使用某个对象的时候,如果重复地new这个对象,不停地申请内存空间,会造成内存空间的极大浪费,在之后程序运行过程中也可能会产生大量的垃圾对象,给服务器的垃圾回收带来极大压力,那么我们从软件设计的角度该如何解决这个问题呢?单例模式就可以解决这个问题了。在之前的单例模式中我们提到” 单例模式提供了一个全局访问点,来访问其唯一的实例对象“,单例模式强调系统中 有且仅有唯一的实例对象。

更进一步,假如系统中就是需要创建多个( 并不是无限制)相同或者相似( 也有可能相同)的对象,那我们该如何处理呢?比如数据库连接,使用的时候不可能每次都创建和销毁,当然也不能使用单例只创建一个连接,负责处理所有的客户端请求,我们可以使用数据连接池技术,创建一定数量的连接的缓存,使用的时直接拿出来使用就可以了,这种模式从创建对象的角度来看也算是”享元模式”的一种典型应用,下面我们就来学习一下该模式。

定义:享元模式(FlyWeight Pattern)主要用来减少创建对象的数量,以减少内存占用,达到提高性能目的,这种模式也属于结构型设计模式,享元模式尝试复用现有的同类对象,如果未找到匹配对象,则创建新对象,此模式是一种专门为提升系统性能而生的设计模式。

要理解享元模式,先来了解两个概念,内部状态和外部状态:

内部状态:在享元对象内部不随外界环境改变而改变的共享部分;

外部状态:随着环境的改变而改变,不能功能构想的状态就是外部状态;

享元模式区分了内部状态和外部状态,所以我们可以通过设置不同的外部状态使得相同的对象可以具备一些不同的特性,而内部状态则设置为相同的共享部分。

享元模式结构图:

角色分析:

1、Flyweight:抽象的享元角色,通常是一个接口或者抽象类,在抽象享元角色中声明了具体享元角色中的公共方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法来设置外部数据(外部状态)

2、ConcreteFlyweight:具体享元角色,继承或实现Flyweight接口,称为享元对象,通常结合单例模式来设计具体享元类,为每一个享元类提供唯一的享元对象;

3、UnsharedConcreteFlyweight:指那些不需要共享的Flyweight子类,它并不强制共享;

4、FlyweightFactory:用来创建并管理Flyweight对象,主要用来确保合理第共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory工厂提供一个已经创建的实例或者新创建一个(如果不存在的话);

举例分析:

例如我们小时经常俄罗斯方块游戏,它每次落下来的图形都不一定相同,假如我们每次都new一个图形的话那么会占用大量内存,体验并不好;其实玩久了我们会发现,它每次落下来的图形就那么 几种,包括”L”型、”M”型、”Z”型、”S”型、”I”型等有限的几种类型,那么我们就可以将这有限的几种类型抽象出来,用享元模式来实现,为了更好地说明享元模式,再高级一点我们给这些图形还带上颜色,下面我们就来具体分析吧:

示例代码:

测试结果:

UML类图:

在上面这个例子中,图形的形状就是内部状态,而颜色我们就可以认为是外部状态。外部状态是相互独立的,而且不影响内部状态。

享元模式的优缺点和使用场景:

优点:极大地减少了内存中相似或者相同对象的数量,节约系统资源、提高系统性能;外部状态相互独立,不影响内部状态;

缺点:为了使对象可以共享,需要分离外部状态和内部状态,是程序逻辑复杂;

使用场景:

1、一个系统中有大量相同或者相似的对象,造成内存的大量耗费;

2、对象的大部分状态都可以外部化,可以将这些外部状态传入到对象中;

享元模式和单例模式比较:

单例模式和享元模式都可以减少系统中对象的创建数量,但是两者还有一些区别,主要包括以下方面的内容:

1、享元模式可以再次创建对象,也可以获取缓存的对象,单例模式严格控制单个进程中只有一个实例对象;

2、享元模式可以通过享元工厂实现对外部的单例,也可以在需要的时候创建更多的实例,单例模式是自身控制,需要增加不属于改对象本身的逻辑;

3、两者都可以实现节省对象的创建;

在JDK中的应用:

ThreadPool线程池、第三方提供的数据库连接池、JDK中的字符串常量池等都使用了享元模式、Integer中也有类似的代码;

从这个例子我们可以看出当i>= -128 && i

Original: https://www.cnblogs.com/wha6239/p/16684572.html
Author: 一只烤鸭朝北走
Title: 设计模式之(11)——享元模式

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/612874/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 解决.net6 Docker容器 DateTime.Now 获取时间相差8小时问题(转载)

    .net6项目中使用DateTime.Now获取到的时间比本地时间要差8小时,但是docker容器中,使用date获取的时间是正确的,网上提供了很多种方法,主要有以下三种方法,其中…

    数据库 2023年6月9日
    0147
  • SpringBoot 整合 MongoDB 实战解说

    在前面的文章中,我们详细的介绍了 MongoDB 的配置和使用,如果你对 MongoDB 还不是很了解,也没关系,在 MongoDB 中有三个比较重要的名词: 数据库、集合、文档!…

    数据库 2023年6月14日
    089
  • [spring]spring中java实现类代替注解开发

    9.使用javaconfig实现代替xml配置 The central artifacts in Spring’s new Java-configuration sup…

    数据库 2023年6月16日
    078
  • MySQL实战45讲 4,5

    04 | 深入浅出索引(上) 索引的出现实际上是为了提高数据查询的效率,就像一本书的目录一样。 [En] The emergence of the index is actuall…

    数据库 2023年5月24日
    0101
  • StoneDB完成华为鲲鹏国产处理器适配认证!

    近日,一体化实时 HTAP 数据库 StoneDB 与华为鲲鹏 920 已完成并通过相互兼容性测试认证,取得 KUNPENG COMPATIBLE 证书及认证徽标的使用权。 该认证…

    数据库 2023年5月24日
    091
  • Qt 保持窗口顶层显示最简单方法

    情景: 当前存在两个窗口或以上,先初始化的窗口会被后初始化的窗口覆盖,从而置于底层, 这时一个最简单的方案就是给需要置于顶层的窗口配置事件过滤器,监听窗口状态,当窗口不属于顶层窗口…

    数据库 2023年6月16日
    0125
  • Redis-数据结构

    Redis key-value结构组织 首先,Redis使用了一个全局哈希表来保存所有的键值对。这个全局哈希表,也就是一个存放哈希桶(entry)的数组。Redis可以用哈希算法算…

    数据库 2023年6月11日
    086
  • Centos7安装Greenplum5.3单机版教程

    环境:centos7 ,Greenplum5.3 1. Greenplum 5.3 下载 安装包下载 https://download.csdn.net/download/Ange…

    数据库 2023年6月14日
    0100
  • 2022年5月数据库排名

    数据来源:https://db-engines.com/en/ranking Original: https://www.cnblogs.com/chujian007/p/1631…

    数据库 2023年6月11日
    080
  • maven配置本地仓库

    https://www.cnblogs.com/javajetty/p/10051156.html maven配置本地仓库 Original: https://www.cnblog…

    数据库 2023年6月9日
    084
  • 重新学习数据库(2)

    单元概述 通过本章的学习能够了解MySQL数据库中多表查询的含义,掌握多表查询的基本写法,掌握特殊的多表查询的写法,掌握内连接和外连接的区别 测试数据脚本 drop TABLE e…

    数据库 2023年6月16日
    0194
  • 使用 yum 在 CentOS7 上安装 MySQL8

    时间:2022-07-13安装版本:MySQL-community-8.0.29 0. 删除MariaDB 在CentOS 7中默认有安装MariaDB,这个是MySQL的分支,通…

    数据库 2023年6月16日
    0102
  • Elasticsearch搜索引擎的使用

    当用户在搜索框输入关键字后,我们要为用户提供相关的搜索结果。 这种需求依赖数据库的模糊查询like关键字可以实现,但是like关键字的效率极低,而且查询需要在多个字段中进行,使用l…

    数据库 2023年6月14日
    0137
  • mysql创建用户并授权

    新建用户 create user ‘username’@’%’ identified by ‘password’; • user_name:要创建用户的名字。• host:表示要这…

    数据库 2023年5月24日
    065
  • AspNetCoreapi 使用 Docker + Centos 7部署

    好久没有更新文章了,前段时间写了一系列的文章放到桌面了,想着修修改改,后来系统中勒索病毒了还被公司网络安全的抓到是我电脑,后来装系统文章给装丢了。然后好长一段时间没有写了。 今天记…

    数据库 2023年6月11日
    0102
  • [javaweb]jsp,jstl,el表达式的使用

    jsp java server page:java服务器前端页面,和servlet一样,用于动态web开发。 特点: 写jsp页面就像在写html html只给用户提供静态数据,j…

    数据库 2023年6月16日
    086
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球