设计模式之享元模式详解(上)

享元模式
1)概述
1.问题

如何避免系统中出现大量相同或相似的对象,同时又不影响客户端程序通过面向对象的方式对这些对象进行操作。

2.解决方案

在逻辑上每一个出现的字符都有一个对象与之对应,然而在物理上它们却共享同一个享元对象,这个对象可以出现在一个字符串的不同地方,相同的字符对象都指向同一个实例。

在享元模式中,存储共享实例对象的地方称为享元池(Flyweight Pool),可以针对每一个不同的字符创建一个享元对象,将其放在享元池中,需要时再从享元池取出。

在这里插入图片描述

2)内部状态和外部状态
1.概述

享元模式以共享的方式高效地支持大量细粒度对象的重用,享元对象能做到共享的关键是区分了内部状态(Intrinsic State)和外部状态(Extrinsic State)。

2.内部状态

内部状态是存储在享元对象内部并且不会随环境改变而改变的状态,内部状态可以共享,如字符的内容,无论在任何环境下字符“a”始终是“a”,都不会变成“b”。

3.外部状态

外部状态是随环境改变而改变的、不可以共享的状态,享元对象的外部状态通常由客户端保存,并在享元对象被创建之后,需要使用的时候再传入到享元对象内部。

一个外部状态与另一个外部状态之间是相互独立的,如字符的颜色,可以在不同的地方有不同的颜色,例如有的“a”是红色的,有的“a”是绿色的,字符的大小也是如此,有的“a”是五号字,有的“a”是四号字,而且字符的颜色和大小是两个独立的外部状态,它们可以独立变化,相互之间没有影响,客户端可以在使用时将外部状态注入享元对象中。

4.总结

因为区分了内部状态和外部状态,所以可以将具有相同内部状态的对象存储在享元池中,享元池中的对象是可以实现共享的,需要的时候就将对象从享元池中取出,实现对象的复用。

通过向取出的对象注入不同的外部状态,可以得到一系列相似的对象,而这些对象在内存中实际上只存储一份。

3)简单案例
1.概述

享元模式结构较为复杂,一般结合工厂模式一起使用,在它的结构图中包含了一个享元工厂类。

2.结构图

在这里插入图片描述

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

  • ConcreteFlyweight(具体享元类):它实现了抽象享元类,其实例称为享元对象;在具体享元类中为内部状态提供了存储空间。通常可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。

  • UnsharedConcreteFlyweight(非共享具体享元类):并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过实例化创建。

  • FlyweightFactory(享元工厂类):享元工厂类用于创建并管理享元对象,它针对抽象享元类编程,将各种类型的具体享元对象存储在一个享元池中,享元池一般设计为一个存储“键值对”的集合,当用户请求一个具体享元对象时,享元工厂提供一个存储在享元池中已创建的实例或者创建一个新的实例(如果不存在的话),返回新创建的实例并将其存储在享元池中。

4.享元工厂类

提供一个用于存储享元对象的享元池,当用户需要对象时,首先从享元池中获取,如果享元池中不存在,则创建一个新的享元对象返回给用户,并在享元池中保存该新增对象。

public class FlyweightFactory {

    //定义一个HashMap用于存储享元对象,实现享元池
    private HashMap flyweights = newHashMap();
    
    public Flyweight getFlyweight(String key) {
        //如果对象存在,则直接从享元池获取
        if (flyweights.containsKey(key)) {
            return (Flyweight) flyweights.get(key);
        } else {
            //如果对象不存在,先创建一个新的对象添加到享元池中,然后返回
            Flyweight fw = newConcreteFlyweight();
            flyweights.put(key, fw);
            return fw;
        }
    }
}
5.核心

享元类的设计是享元模式的核心,在享元类中要将内部状态和外部状态分开处理,通常将内部状态作为享元类的成员变量,而外部状态通过注入的方式添加到享元类中。

public class Flyweight {

    //内部状态intrinsicState作为成员变量,同一个享元对象其内部状态是一致的
    private String intrinsicState;

    public  Flyweight(String intrinsicState) {
        this.intrinsicState=intrinsicState;
    }

    //外部状态extrinsicState在使用时由外部设置,不保存在享元对象中,即使是同一个对象,在每一次调用时也可以传入不同的外部状态
    public void operation(String  extrinsicState) {
              ......
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LabVIEW动车组谐波分析与检测系统

LabVIEW动车组谐波分析与检测系统 随着中国高速铁路网络的快速发展,动车组数量和运行速度的不断提升,其产生的谐波问题对电网产生了不小的影响。基于图形化编程语言LabVIEW,开发了一套动车组谐波分析与检测系统,旨在实时监控与分…

《2023腾讯云容器和函数计算技术实践精选集》--在 K8s 上跑腾讯云 Serverless 函数,打破传统方式造就新变革

目录 目录 前言 《2023腾讯云容器和函数计算技术实践精选集》带来的思考 1、特色亮点 2、阅读体验 3、实用建议 4、整体评价 Serverless 和 K8s 的优势 1、关于Serverless 函数的特点 2、K8s 的特点 腾讯云 Serverless 函数在 K8s 上的应用对企业服务的影响 案例分…

wps 开发插件

官方文档参考wps官方文档参考 1.环境安装 安装wps https://www.wps.cn/ 安装Node.js https://nodejs.org/en 安装代码编辑器 Visual Studio Code https://code.visualstudio.com/ 环境检查-进入cmd查看 node -v2.demo 2.1 demo下载 打开vscode,新建终端 安装…

Docker工作流

1.工作流 开发应用编写Dockerfile构建Docker镜像运行Docker容器测试应用发布镜像到Hub迭代更新镜像 2.开发应用 首先你需要创建一个应用,这个应用可以是后端应用或者前端应用,任何语言都可以。 比如:我使用IDEA 创建一个Java后端应用&…

用Typora+picgo+cloudflare+Telegraph-image的免费,无需服务器,无限空间的图床搭建(避坑指南)

用TyporapicgocloudflareTelegraph-image的免费,无需服务器,无限空间的图床搭建(避坑指南) 前提:有github何cloudflare (没有的话注册也很快) 首先,是一个别人写的详细的配置流程,傻瓜式教程&am…

spring boot自动配置原理-怎样回答这个问题

首先我们说一下自动配置的概念。 自动配置:遵循约定大约配置的原则,在boot程序启动后,起步依赖中的一些bean对象会自动注入到ioc容器 例子 程序引入spring-boot-starter-web 起步依赖,启动后,会自动往ioc容器中注入…

云计算面临的威胁

目录 一、概述 二、威胁建模分析 2.1 威胁建模的概念 2.2 威胁建模起到的作用 2.3 威胁建模的流程 2.3.1 威胁建模流程图 2.3.2 威胁建模流程内容 2.3.2.1 绘制数据流图 2.3.2.2 威胁识别与分析 2.3.2.2.1 STRIDE威胁分析方法论 2.3.2.3 制定消减措施 2.3.2.3.1 消减…

UDE-12154: 操作产生了 ORACLE 错误 12154ORA-12154: TNS: 无法解析指定的连接标识符

在连接远程数据库时出的错 加个ip地址咯 原本: 代码: expdp TEST/TESTORCLDB schemasTEST directoryexportW dumpfileexport_data.dmp logfileexport_log.log 解决问题: 代码: expdp TEST/TEST*.*.*.*/ORCLDB schemasTEST dir…

FMEA引领智能家居安全革新,打造无忧智能生活新纪元!

在智能家居日益普及的今天,如何确保家居安全成为消费者关注的焦点。本文将探讨如何通过FMEA(故障模式与影响分析)这一强大的质量管理工具,为智能家居赋能,打造安全无忧的智能生活新体验。 一、FMEA在智能家居领域的应用…

使用Docker快速搭建Kafka

前言 今天讲下如何使用Docker快速搭建kafka。 前期准备,需要安装好docker、docker-compose。 一、安装Kafka 1、创建Kafka目录,执行如下命令。 mkdir -p /docker/kafka/ cd /docker/kafka/ 2、编写yaml文件,内容如下。 vim docker-com…

【面试八股总结】超文本传输协议HTTP(二)

一、HTTP缓存技术 将资源(如网页、图像、脚本等)的副本存储在客户端或中间代理服务器上,以便将来的请求可以直接从缓存中获取,而不必重新从服务器下载资源。这有助于减少网络延迟,提高页面加载速度,并减轻…

算法2.7:排序算法之间的比较

排序算法间的比较 比较元素: 1,平均时间复杂度 2,最好情况 3,最坏情况 4,空间复杂度 5,排序方式 6,稳定性 部分术语解释: 1,稳定:如果a本来在b前面,ab,排序之后a仍然在b前面 2,不稳定:即!第一条 3,内排序:所有排序操作都在内存中完成 4,外排序:需要借助外界的存储空…

电脑win10系统更新后开机很慢,更新win10后电脑开机怎么变慢了

很多用户反映,更新win10后电脑开机怎么变慢了呢?现在动不动就要30几秒,以前都是秒开机的,要怎么设置才能提高开机速度?小伙伴们别着急,主要原因可能是关机设置中没有勾选启用快速启动,或者是开机启动设置的问题&…

缓存(反向代理)服务器-varnish

varnish简介: varnish是一款高性能且开源的反向代理服务器和HTTP加速器,(其实就是带缓存的反向代理服务器)它可以把整个HTTP响应内容缓存到内存或文件中,从而提高web服务器器的响应速度。 与传统的squid相比&#xff0…

NBU备份oracle详细配置文档(含常见报错处理方法)

​前提 NBU master和media服务器已经配置OK,现在需要oracle主机安装agent并配置备份任务。 NBU master版本8.3.0.2 Oracle OS版本redhat 6.8 Oracle版本 11.2.0.4 1.Oracle 安装agent 下载安装档 https://www.veritas.com/content/support/zh_CN 选择…

【opencv】教程代码 —xfeatures2D 使用LATCH算法提取特征描述子的图像特征匹配程序...

LATCH_match.cpp 这段代码是使用C以及OpenCV库来实现图像特征匹配的程序。它主要包括了使用ORB算法检测关键点并使用LATCH算法提取特征描述子的步骤,之后使用暴力匹配方法(Brute-Force Matching)和比率测试来筛选出好的匹配点,最后…

蓝桥杯单片机速成1--138锁存器

一、原理图 大家都知道,蓝桥杯单片机比赛用的板子的原理就是51的原理,但二者唯一的区别就是这个74HC138锁存器,因为比赛用板的LED,数码管,蜂鸣器和继电器都在P0口上,所以为了防止错乱,加了一个…

本地运行github上下载的项目--接Git入门篇

1.了解项目 这是一个基于Spring Boot 和 Mybatis Plus 构建的Java项目,很经典的外卖项目,参考b站的黑马瑞吉外卖。 2.构建项目 SpringBoot项目,首先下载一些常见的项目要求的组件。然后配置如下: 看README,在阅读该…

LeetCode-48. 旋转图像【数组 数学 矩阵】

LeetCode-48. 旋转图像【数组 数学 矩阵】 题目描述:解题思路一:一行代码!Python zip函数图一乐【zip函数实现主对角线翻转,[::-1]实现垂直翻转】解题思路二:其实我们也可以先水平轴翻转,让后主对角线翻转。…

xss-lab 1-10关过关记录

前言 最近发现xss学的知识点都忘干净了,来打一打靶子并且记录一下这些过关经历。 level1 特性: 1.get型传参 2.无任何过滤 过关操作: 直接构造payload传参过关 level2 get型传参 我们在输入框中输入payload发现并没有弹窗。 查看网页…