【设计模式】结构型模式(四):组合模式、享元模式

news2024/11/13 10:03:28

设计模式之结构型模式》系列,共包含以下文章:

  • 结构型模式(一):适配器模式、装饰器模式
  • 结构型模式(二):代理模式
  • 结构型模式(三):桥接模式、外观模式
  • 结构型模式(四):组合模式、享元模式

😊 如果您觉得这篇文章有用 ✔️ 的话,请给博主一个一键三连 🚀🚀🚀 吧 (点赞 🧡、关注 💛、收藏 💚)!!!您的支持 💖💖💖 将激励 🔥 博主输出更多优质内容!!!

结构型模式(四):组合模式、享元模式

  • 6.组合模式(Composite)
    • 6.1 案例
      • 6.1.1 定义统一接口
      • 6.1.2 实现叶子节点(文件)
      • 6.1.3 实现组合节点(文件夹)
      • 6.1.4 客户端
      • 6.1.5 输出
  • 7.享元模式(Flyweight)
    • 7.1 问题
    • 7.2 解决方案
    • 7.3 代码实现
      • 7.3.1 享元接口
      • 7.3.2 享元对象
      • 7.3.3 享元工厂
      • 7.3.4 客户端
      • 7.3.5 输出结果

6.组合模式(Composite)

组合模式Composite Pattern)是一种设计模式,用于处理树形结构的数据。它的主要目的是将对象组合成树形结构来表示 “部分 - 整体” 的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

在这里插入图片描述

具体来说,组合模式有以下几个特点:

  • 统一接口:无论是单个对象(叶子节点)还是组合对象(树枝节点),都提供相同的接口,这样客户端代码可以一致地处理它们,而不需要关心它们是单个对象还是组合对象。
  • 递归结构:组合模式通过 **递归 **的方式构建树形结构,每个组合对象可以包含多个子对象,这些子对象可以是叶子节点或更深层次的组合对象。
  • 透明性:客户端代码不需要关心对象的具体类型,只需要通过统一的接口进行操作。

6.1 案例

假设你正在开发一个文件系统,文件系统中包含文件(File)和文件夹(Folder)。文件夹可以包含多个文件和其他文件夹,文件夹和文件都有一些共同的操作,比如显示内容。
在这里插入图片描述

6.1.1 定义统一接口

public interface Component {
 void display();
}

6.1.2 实现叶子节点(文件)

public class File implements Component {
    private String name;

    public File(String name) {
        this.name = name;
    }

    @Override
    public void display() {
        System.out.println("文件: " + name);
    }
}

6.1.3 实现组合节点(文件夹)

import java.util.ArrayList;
import java.util.List;

public class Folder implements Component {
   private String name;
   private List<Component> children = new ArrayList<>();

   public Folder(String name) {
       this.name = name;
   }

   public void add(Component component) {
       children.add(component);
   }

   public void remove(Component component) {
       children.remove(component);
   }

   @Override
   public void display() {
       System.out.println("文件夹: " + name);
       for (Component child : children) {
           child.display();
       }
   }
}

6.1.4 客户端

public class CompositePatternExample {
   public static void main(String[] args) {
       // 创建文件和文件夹
       File file1 = new File("文件1");
       File file2 = new File("文件2");
       Folder folder1 = new Folder("文件夹1");
       Folder folder2 = new Folder("文件夹2");

       // 组合文件和文件夹
       folder1.add(file1);
       folder1.add(file2);
       folder2.add(folder1);
       folder2.add(new File("文件3"));

       // 显示文件系统结构
       folder2.display();
   }
}

6.1.5 输出

文件夹: 文件夹2
文件夹: 文件夹1
文件: 文件1
文件: 文件2
文件: 文件3

在这个例子中,Component 接口定义了所有组件的共同操作,FileFolder 都实现了这个接口。Folder 可以包含多个 Component,从而形成树形结构。客户端代码通过 Component 接口操作文件和文件夹,而不需要关心它们的具体类型。

7.享元模式(Flyweight)

享元模式Flyweight Pattern) 是一种用于性能优化的设计模式,主要目的是通过共享已经存在的对象来减少内存使用和提高性能。简单来说,享元模式 通过共享对象来减少对象的数量,从而节省内存

在这里插入图片描述
假设你正在开发一个文本编辑器,用户可以在编辑器中输入大量的文本。为了显示这些文本,你需要为每个字符创建一个对象。如果每个字符都创建一个独立的对象,那么当文本非常大时,会占用大量的内存。

7.1 问题

  • 内存消耗大:如果每个字符都创建一个独立的对象,内存消耗会非常大。
  • 性能问题:创建和管理大量对象会导致性能下降。

7.2 解决方案

使用享元模式,你可以共享字符对象,而不是为每个字符都创建一个独立的对象。具体来说:

  • 内部状态Intrinsic State):这些是共享的、不变的状态,例如字符的字形信息。
  • 外部状态Extrinsic State):这些是不共享的、变化的状态,例如字符在文档中的位置。

🚀 计算机世界中无穷无尽的可能,其本质都是由 10 两个“元”的组合变化而产生的。
🚀 ,顾名思义,始也,有本初、根源的意思。“享元” 则是 共享元件 的意思。享元模式的英文 Flyweight轻量级 的意思,这就意味着享元模式能使程序变得更加轻量化。当系统存在大量的对象,并且这些对象又具有相同的内部状态时,我们就可以用享元模式共享相同的元件对象,以避免对象泛滥造成资源浪费。

7.3 代码实现

假设你有一个文本编辑器,需要显示大量的字符。你可以使用享元模式来减少内存使用。

7.3.1 享元接口

public interface CharacterFlyweight {
   void display(int position);
}
  • 定义了一个接口,用于显示字符及其位置。
  • 方法:display(int position),用于显示字符在文本中的位置。

7.3.2 享元对象

public class CharacterObject implements CharacterFlyweight {
    private final char value;
    private final String font;

    public CharacterObject(char value, String font) {
        this.value = value;
        this.font = font;
    }

    @Override
    public void display(int position) {
        System.out.println("Character: " + value + " at position: " + position + " with font: " + font);
    }
}

Character 类实现了 CharacterFlyweight 接口,包含字符的值和字体信息。这些信息是内部状态,是共享的。

7.3.3 享元工厂

import java.util.HashMap;
import java.util.Map;

public class CharacterFactory {
    private static final Map<Character, CharacterFlyweight> pool = new HashMap<>();

    public static CharacterFlyweight getCharacter(char value, String font) {
        CharacterFlyweight character = pool.get(value);
        if (character == null) {
            // 创建新的 CharacterFlyweight 对象
            System.out.println("===============: " + value + " 加入共享");
            character = new CharacterObject(value, font);
            // 将新创建的对象添加到 pool 中
            pool.put(value, character);
        }
        return character;
    }
}

CharacterFactory 类是一个工厂类,用于管理共享的字符对象。通过 getCharacter 方法,根据字符值和字体信息从池中获取或创建字符对象。

为什么 CharacterFactory 不需要实现 CharacterFlyweight 接口?

  • 职责分离CharacterFactory 的职责是创建和管理 CharacterFlyweight 对象,而不是实现 CharacterFlyweight 接口。实现接口的类应该是具体的字符对象类,如 CharacterObject
  • 灵活性:通过工厂类创建对象,可以在不改变调用代码的情况下,轻松地更换不同的实现类。例如,如果将来需要添加一个新的字符对象实现类 CharacterObject2,只需要在 CharacterFactory 中创建 CharacterObject2 的实例即可。
  • 解耦:调用者只需要知道 CharacterFlyweight 接口,而不需要知道具体的实现类。这有助于降低代码的耦合度,提高代码的可维护性和扩展性。

CharacterFactory 类中,getCharacter 方法负责创建 CharacterFlyweight 对象。具体来说,当 pool 中没有指定字符的 CharacterFlyweight 对象时,getCharacter 方法会创建一个新的 CharacterObject 实例,并将其添加到 pool 中。

7.3.4 客户端

public class FlyweightPatternExample {
   public static void main(String[] args) {
       // 模拟输入文本
       String text = "Hello, World!";

       for (int i = 0; i < text.length(); i++) {
           char c = text.charAt(i);
           CharacterFlyweight character = CharacterFactory.getCharacter(c, "Arial");
           character.display(i);
       }
   }
}

客户端代码通过 CharacterFactory 获取字符对象,并调用 display 方法显示字符。每个字符对象在池中只创建一次,多次使用时直接从池中获取,从而减少了内存使用。

7.3.5 输出结果

===============: H 加入共享
Character: H at position: 0 with font: Arial
===============: e 加入共享
Character: e at position: 1 with font: Arial
===============: l 加入共享
Character: l at position: 2 with font: Arial
Character: l at position: 3 with font: Arial
===============: o 加入共享
Character: o at position: 4 with font: Arial
===============: , 加入共享
Character: , at position: 5 with font: Arial
===============:   加入共享
Character:   at position: 6 with font: Arial
===============: W 加入共享
Character: W at position: 7 with font: Arial
Character: o at position: 8 with font: Arial
===============: r 加入共享
Character: r at position: 9 with font: Arial
Character: l at position: 10 with font: Arial
===============: d 加入共享
Character: d at position: 11 with font: Arial
===============: ! 加入共享
Character: ! at position: 12 with font: Arial

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

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

相关文章

众测遇到的一些案列漏洞

文章中涉及的敏感信息均已做打码处理,文章仅做经验分享用途,切勿当真,未授权的攻击属于非法行为!文章中敏感信息均已做多层打码处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任,一旦造成后果请自行…

算法求解(C#)-- 寻找包含目标字符串的最短子串算法

1. 引言 在字符串处理中&#xff0c;我们经常需要从一个较长的字符串中找到包含特定目标字符串的最短子串。这个问题在文本搜索、基因序列分析等领域有着广泛的应用。本文将介绍一种高效的算法来解决这个问题。 2. 问题描述 给定一个源字符串 source 和一个目标字符串 targe…

ThingsBoard规则链节点:RPC Call Reply节点详解

引言 1. RPC Call Reply 节点简介 2. 节点配置 2.1 基本配置示例 3. 使用场景 3.1 设备控制 3.2 状态查询 3.3 命令执行 4. 实际项目中的应用 4.1 项目背景 4.2 项目需求 4.3 实现步骤 5. 总结 引言 ThingsBoard 是一个开源的物联网平台&#xff0c;提供了设备管理…

动态规划(简单多状态 dp 问题 1.按摩师 2.打家劫舍 II 3. 删除并获得点数 4.粉刷房子 5.买卖股票的最佳时机(全系列))

面试题 17.16. 按摩师213. 打家劫舍 II740. 删除并获得点数LCR 091. 粉刷房子 &#xff08;原&#xff1a;剑指 Offer II 091. 粉刷房子&#xff09;309. 买卖股票的最佳时机含冷冻期714. 买卖股票的最佳时机含手续费123. 买卖股票的最佳时机 III188. 买卖股票的最佳时机 IV 1.…

【VBA实战】用Excel制作排序算法动画续

为什么会产生用excel来制作排序算法动画的念头&#xff0c;参见【VBA实战】用Excel制作排序算法动画一文。这篇文章贴出我所制作的所有排序算法动画效果和源码&#xff0c;供大家参考。 冒泡排序&#xff1a; 插入排序&#xff1a; 选择排序&#xff1a; 快速排序&#xff1a;…

关于Markdown的一点疑问,为什么很多人说markdown比word好用?

markdown和word压根不是一类工具&#xff0c;不存在谁比谁好&#xff0c;只是应用场景不一样。 你写博客、写readme肯定得markdown&#xff0c;但写合同、写简历肯定word更合适。 markdown和word类似邮箱和微信的关系&#xff0c;这两者都可以通信&#xff0c;但微信因为功能…

区块链技术在数字版权管理中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 区块链技术在数字版权管理中的应用 区块链技术在数字版权管理中的应用 区块链技术在数字版权管理中的应用 引言 区块链技术概述 …

基于Spring Boot的在线装修管理系统的设计与实现,LW+源码+讲解

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差&#…

Ollama 0.4 发布!支持 Llama 3.2 Vision,实现多模态 RAG

“ 阅读本文大概需要5分钟。 前言 最近&#xff0c;Ollama 推出了 0.4 版本&#xff0c;其中最大的亮点就是支持了 Llama 3.2 Vision 模型&#xff0c;该模型具备多模态特性&#xff0c;也就是说能够理解图像并将图像纳入提示词中进行处理&#xff0c;让模型更智能地处理RAG中…

关于若依500验证码问题的求助

关于若依框架中验证码出现500错误的问题&#xff0c;这通常表示服务器内部错误。以下是一些可能的原因及解决方案&#xff1a; 一、配置文件问题 .env.production文件&#xff1a; 确保.env.production文件中的VUE_APP_BASE_API已经修改成服务器上的域名地址&#xff0c;而不…

使用HtmlAgilityPack+PuppeteerSharp+iText7抓取IdentityServer4帮助文档

需要学习IdentityServer4的用法&#xff0c;但是在IdentityServer4帮助文档网站&#xff08;参考文献1&#xff09;中没有找到下载离线文档的地方&#xff0c;准备使用HtmlAgilityPackPuppeteerSharpiText7将网站内容抓取生成离线PDF文档&#xff0c;便于本机学习、查看。   …

fpga开发原理图设计仿真分析

目录 原理图设计方法的流程 仿真分析 method1. 基于向量波形的仿真方法 method2. 基于testbench的仿真方法 在Quartus Prime开发环境下&#xff0c;进行EDA设计的基本流程如图所示。 包括五个主要任务: (1) 建立工程 (2) 设计输入 (3) 编译、综合与适配 (4) 引脚…

Node.js——fs模块-路径补充说明

1、相对路径&#xff1a; ./座右铭.txt 当前目录下的座右铭.txt座右铭.txt 等效于上面的写法../座右铭.txt 当前目录的上一级目录中的座右铭.txt 2、绝对路径 D&#xff1a;/Program File Windows系统下的绝对路径/usr/bin Linux系统…

从0开始搭建一个生产级SpringBoot2.0.X项目(十)SpringBoot 集成RabbitMQ

前言 最近有个想法想整理一个内容比较完整springboot项目初始化Demo。 SpringBoot集成RabbitMQ RabbitMQ中的一些角色&#xff1a; publisher&#xff1a;生产者 consumer&#xff1a;消费者 exchange个&#xff1a;交换机&#xff0c;负责消息路由 queue&#xff1a;队列…

比流计算资源效率最高提升 1000 倍,“增量计算”新模式能否颠覆数据分析?

作者 | 关涛 云器科技CTO 数据平台领域发展 20 年&#xff0c;逐渐成为每个企业的基础设施。作为一个进入“普惠期”的领域&#xff0c;当下的架构已经完美了吗&#xff0c;主要问题和挑战是什么&#xff1f;在 2023 年 AI 跃变式爆发的大背景下&#xff0c;数据平台又该如何演…

MySQL性能测试方案设计

在现代互联网系统中&#xff0c;数据库性能直接影响到整体应用的速度和用户体验。而MySQL作为广泛使用的关系型数据库&#xff0c;随着数据量和并发请求的增长&#xff0c;其性能问题也日益突出。今天我们将深入探讨如何设计一套高效的MySQL性能测试方案&#xff0c;帮助你精准…

彻底解决单片机BootLoader升级程序失败问题

文章目录 1、引言2、MicroBoot&#xff1a;优雅的解决升级问题问题1&#xff1a;bootloader 在跳转到app前没有清理干净存在的痕迹问题2&#xff1a; 需要 APP 传递信息给 Bootloader问题3&#xff1a; APP单独运行没有问题&#xff0c;通过Bootloader跳转到APP运行莫名死机问题…

Oracle OCP认证考试考点详解082系列17

题记&#xff1a; 本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 81. 第81题&#xff1a; 题目 81.Examine these SOL statements which execute successfully Which two statements are true after exec…

【EFK】Linux集群部署Elasticsearch最新版本8.x

【EFK】Linux集群部署Elasticsearch最新版本8.x 摘要环境准备环境信息系统初始化启动先决条件 下载&安装修改elasticsearch.yml控制台启动Linux服务启动访问验证查看集群信息查看es健康状态查看集群节点查询集群状态 生成service token验证service tokenIK分词器下载 摘要 …

基于python的天气数据采集与可视化分析,对20个城市的天气适宜出行度分析

摘要 本项目旨在基于Python对20个城市的天气数据进行采集与可视化分析&#xff0c;以评估天气的适宜出行度。该分析通过四个主要指标进行量化&#xff0c;这些指标分别是天气状况良好率、空气质量优良率、气温适宜率和安全天气率。通过这些指标&#xff0c;我们能够有效地判断…