Flyweight(享元)

1)意图

运用共享技术有效地支持大量细粒度的对象。

2)结构

享元模式的结构如图 7-36 所示。
在这里插入图片描述
其中:

  • Flyweight 描述一个接口,通过这个接口 Flyweight 可以接受并作用于外部状态

  • ConcreteFlyweight 实现 Flyweight 接口,并为内部状态(如果有)增加存储空间。ConcreteFlywweight 对象必须是可共享的。它所存储的状态必须是内部的,即它必须独立于 ConcreteFlyweight 对象的场景。

  • 并非所有的 Flyweight 子类都需要被共享。Flywweight 接口使共享成为可能,但它并不强制共享。在 Flyweight 对象结构的某些层次,UnsharedConcreteFlyweight 对象通常将ConcreteFlyweight 对象作为子结点。

  • FlyweightFactory 创建并管理 Flyweight 对象;确保合理地共享 Flyweight,当用户请求一个 Flyweight 时,FlyweightFactony 对象提供一个已创建的实例或者在不存在时创建一个实例。

  • Client 维持一个对 Flyweight 的引用;计算或存储一个或多个 Flyweight 的外部状态。

3)适用性

Flyweight 模式适用于:

  • 一个应用程序使用了大量的对象。

  • 完全由于使用大量的对象,造成很大的存储开销。

  • 对象的大多数状态都可变为外部状态。

  • 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。

  • 应用程序不依赖于对象标识。由于 Flyweight 对象可以被共享,所以对于概念上明显有别的对象,标识测试将返回真值。

4 应用举例

示例:商品展示

  • 场景描述

假设我们正在开发一个电子商务网站,该网站上有成千上万种商品。每种商品都有许多属性,如名称、价格、描述、图片等。如果每次加载页面时都为每个商品创建一个完整的对象,将会消耗大量的内存资源。使用Flyweight模式可以帮助我们减少内存使用,提高页面加载速度。

  • 实现步骤
  1. 定义享元接口

首先,定义一个接口来表示商品的基本功能。

public interface Product {
    void display();
}
  1. 创建具体享元类

然后,实现这个接口的具体类,例如ConcreteProduct,用来表示具体的商品。

public class ConcreteProduct implements Product {
    private String name;
    private double price;
    private String description;

    public ConcreteProduct(String name, double price, String description) {
        this.name = name;
        this.price = price;
        this.description = description;
    }

    @Override
    public void display() {
        System.out.println("Product Name: " + name);
        System.out.println("Price: $" + price);
        System.out.println("Description: " + description);
    }
}
  1. 创建享元工厂

接下来,创建一个工厂类来管理这些商品对象,确保相同的商品只创建一次,并且可以被多次复用。

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

public class ProductFactory {
    private static final Map<String, Product> products = new HashMap<>();

    public static Product getProduct(String key) {
        if (!products.containsKey(key)) {
            // 假设key是一个包含了商品名称、价格和描述的字符串
            String[] parts = key.split(",");
            products.put(key, new ConcreteProduct(parts[0], Double.parseDouble(parts[1]), parts[2]));
        }
        return products.get(key);
    }
}
  1. 在Web应用中使用享元

在Web应用中,当用户访问商品列表页面时,根据商品ID从工厂中获取相应的商品对象,并显示这些商品。

public class ECommerceWebsite {
    public static void main(String[] args) {
        // 模拟用户访问商品列表页面
        Product product1 = ProductFactory.getProduct("Laptop,999.99,A high-performance laptop for gaming and work");
        Product product2 = ProductFactory.getProduct("Laptop,999.99,A high-performance laptop for gaming and work"); // 不会创建新的对象
        Product product3 = ProductFactory.getProduct("Smartphone,699.99,A sleek and powerful smartphone with a great camera");

        product1.display(); // 显示商品1
        product2.display(); // 显示商品2
        product3.display(); // 显示商品3
    }
}

通过上述实现,即使有成千上万的商品具有相同的属性,系统也只需要维护一个对应的ConcreteProduct对象。这样不仅减少了内存的使用,还提高了页面加载速度,特别是在高并发的情况下,这种优化尤为重要。

在Web开发中,Flyweight模式可以有效地帮助我们管理大量相似的对象,减少资源消耗,提高应用性能。特别是在涉及商品展示、用户评论、文章列表等场景下,该模式能够发挥重要作用。通过共享相同的数据,我们可以显著提高系统的效率和响应速度。

示例:在线学习平台

在Web开发中,Flyweight(享元)模式同样有其应用场景,尤其是在处理大量相似的数据对象时,可以显著提高性能和减少内存使用。下面以一个在线学习平台为例,说明如何在Web开发中使用享元模式。

  • 场景描述

假设我们正在构建一个在线学习平台,用户可以在平台上观看课程视频、阅读文章和参与讨论。为了提供个性化的用户体验,平台需要存储用户的偏好设置,例如字体大小、主题颜色等。如果每个用户的偏好设置都独立存储为一个完整的对象,当用户数量非常大时,这将占用大量的内存资源。这时,可以采用享元模式来优化。

  • 实现步骤
  1. 定义享元接口

首先,定义一个接口来表示用户偏好设置的功能。

public interface UserPreference {
    void applySettings();
}
  1. 创建具体享元类

然后,实现这个接口的具体类,例如UserSetting,用来表示具体的用户设置。

public class UserSetting implements UserPreference {
    private String themeColor;
    private int fontSize;

    public UserSetting(String themeColor, int fontSize) {
        this.themeColor = themeColor;
        this.fontSize = fontSize;
    }

    @Override
    public void applySettings() {
        System.out.println("Applying settings: Theme Color - " + themeColor + ", Font Size - " + fontSize);
    }
}
  1. 创建享元工厂

接下来,创建一个工厂类来管理这些设置对象,确保相同的设置只创建一次,并且可以被多次复用。

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

public class PreferenceFactory {
    private static final Map<String, UserPreference> preferences = new HashMap<>();

    public static UserPreference getUserPreference(String key) {
        if (!preferences.containsKey(key)) {
            // 假设key是一个包含了主题颜色和字体大小的字符串
            String[] parts = key.split(",");
            preferences.put(key, new UserSetting(parts[0], Integer.parseInt(parts[1])));
        }
        return preferences.get(key);
    }
}
  1. 在Web应用中使用享元

在Web应用中,当用户登录时,根据用户的偏好设置获取相应的UserPreference对象,并应用这些设置。

public class OnlineLearningPlatform {
    public static void main(String[] args) {
        // 模拟用户A和用户B登录,他们有相同的偏好设置
        UserPreference userAPref = PreferenceFactory.getUserPreference("dark,14");
        UserPreference userBPref = PreferenceFactory.getUserPreference("dark,14"); // 不会创建新的对象

        userAPref.applySettings(); // 应用用户A的偏好设置
        userBPref.applySettings(); // 应用用户B的偏好设置

        // 模拟用户C登录,有不同的偏好设置
        UserPreference userCPref = PreferenceFactory.getUserPreference("light,12");
        userCPref.applySettings(); // 应用用户C的偏好设置
    }
}

通过上述实现,即使有成千上万的用户具有相同的偏好设置,系统也只需要维护一个对应的UserSetting对象。这样不仅减少了内存的使用,还提高了系统的响应速度,特别是在高并发的情况下,这种优化尤为重要。

在Web开发中,Flyweight模式可以有效地帮助我们管理大量相似的对象,减少资源消耗,提高应用性能。特别是在涉及用户个性化设置、界面组件等场景下,该模式能够发挥重要作用。

示例:文本编辑器中的字符格式化

Flyweight(享元)模式是一种用于性能优化的模式,主要用于减少创建大量对象所造成的内存开销。通过共享尽可能多的信息来有效地支持大量的细粒度的对象。享元模式特别适用于对象的大部分状态可以外部化的情况,也就是说这些信息可以从对象中移除并作为参数传入到对象的方法中。

  • 应用场景

一个典型的应用场景是文本编辑器中的字符格式化。在大型文档中,如果每个字符都包含自己的格式设置(如字体、大小、颜色等),将会消耗大量的内存。使用享元模式,可以将相同的格式设置共享给多个字符,从而节省内存空间。

  • 应用实例

假设我们正在开发一个简单的文本编辑器,需要处理带有不同格式的文本。为了提高效率,我们可以使用享元模式来实现字体格式的共享。

  1. 定义享元接口

首先,定义一个表示字符格式的接口或抽象类,这里我们使用接口CharacterFormat

public interface CharacterFormat {
    void display(char character);
}
  1. 创建具体享元类

然后,实现这个接口的具体类,比如FontFormat,它代表了具体的字体格式。

public class FontFormat implements CharacterFormat {
    private String fontName;
    private int fontSize;
    private String color;

    public FontFormat(String fontName, int fontSize, String color) {
        this.fontName = fontName;
        this.fontSize = fontSize;
        this.color = color;
    }

    @Override
    public void display(char character) {
        System.out.println("Character: " + character + " with Font: " + fontName + ", Size: " + fontSize + ", Color: " + color);
    }
}
  1. 创建享元工厂

接着,我们需要一个工厂类来管理这些格式化的实例,确保相同的格式只创建一次,并且可以被多次使用。

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

public class FormatFactory {
    private static final Map<String, CharacterFormat> formats = new HashMap<>();

    public static CharacterFormat getFormat(String key) {
        if (!formats.containsKey(key)) {
            // 假设key是一个包含了字体名称、大小和颜色的字符串
            String[] parts = key.split(",");
            formats.put(key, new FontFormat(parts[0], Integer.parseInt(parts[1]), parts[2]));
        }
        return formats.get(key);
    }
}
  1. 使用享元

最后,在实际的应用程序中,当我们需要显示某个特定格式的字符时,可以通过FormatFactory获取已经存在的格式对象,或者如果该对象不存在,则由工厂创建一个新的对象。

public class TextEditor {
    public static void main(String[] args) {
        CharacterFormat format1 = FormatFactory.getFormat("Arial,12,red");
        CharacterFormat format2 = FormatFactory.getFormat("Arial,12,red"); // 这里不会创建新的对象
        
        format1.display('H');
        format2.display('e');
        
        // 显示不同的格式
        CharacterFormat format3 = FormatFactory.getFormat("Times New Roman,14,blue");
        format3.display('l');
    }
}

在这个例子中,即使两次请求了相同的字体格式,FormatFactory也只会返回同一个FontFormat对象,这样就避免了不必要的内存消耗。通过这种方式,享元模式帮助我们在处理大量相似对象时提高了应用程序的性能。

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

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

相关文章

微信小程序中使用离线版阿里云矢量图标

前言 阿里矢量图库提供的在线链接服务仅供平台体验和调试使用&#xff0c;平台不承诺服务的稳定性&#xff0c;企业客户需下载字体包自行发布使用并做好备份。 1.下载图标 将阿里矢量图库的图标先下载下来 解压如下 2.转换格式 贴一个地址用于转换格式&#xff1a;Onlin…

大数据之多级缓存方案

多级缓存介绍&#xff1f;多级缓存优缺点&#xff0c;应用场景&#xff1f;多级缓存架构&#xff1f; 多级缓存介绍 多级缓存方案是一种优化手段&#xff0c;通过在多个级别上存储数据来提高应用程序的性能和响应速度。以下是对多级缓存方案的详细解析&#xff1a; 一、多级缓…

jupyter notebook启动和单元格cell

【注意&#xff01;&#xff01;&#xff01;】 本章主要讲解数据分析、挖掘入门及进阶知识 - 通过多篇文章【文字案例】的形式系统化进行描述 数据分析专栏&#xff1a;https://blog.csdn.net/2201_75422674/category_12827743.html - 大家喜欢可以订阅一下&#xff0c;不收费…

街道网格领域的数据大屏,在社区治理方面大显身手。

街道网格领域的数据大屏在社区治理中发挥着重要作用。它可以直观地展示社区的人口分布、治安状况、环境问题等各类信息。 通过实时更新的数据&#xff0c;社区工作人员能够及时掌握动态变化&#xff0c;迅速做出决策。色彩鲜明的图表和图形让复杂的数据一目了然&#xff0c;方…

14、NAT和桥接区别

一、NAT模式 NAT相当于是局域网中的局域网&#xff0c;把192.168.21.1当作外网ip&#xff0c;重新划分了一个网关&#xff08;192.168.33.x&#xff09; 二、桥接模式 网桥只是把网络桥接起来&#xff0c;还是原来的网关&#xff08;192.168.21.x&#xff09;&#xff0c;虚拟机…

k8s 处理namespace删除一直处于Terminating —— 筑梦之路

问题现象 k8s集群要清理某个名空间&#xff0c;把该名空间下的资源全部删除后&#xff0c;删除名空间&#xff0c;一直处于Terminating状态&#xff0c;无法完全清理掉。 如何处理 为什么要记录下这个处理的步骤&#xff0c;经过查询资料&#xff0c;网上也有各种各样的方法&…

鸿蒙多线程开发——Worker多线程

1、概 述 1.1、基本介绍 Worker主要作用是为应用程序提供一个多线程的运行环境&#xff0c;可满足应用程序在执行过程中与主线程分离&#xff0c;在后台线程中运行一个脚本进行耗时操作&#xff0c;极大避免类似于计算密集型或高延迟的任务阻塞主线程的运行。 创建Worker的线…

Python实现SSA智能麻雀搜索算法优化BP神经网络回归模型(优化权重和阈值)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后关注获取。 1.项目背景 随着人工智能技术的发展&#xff0c;机器学习算法在各个领域的应用越来越广泛。其中&#xff0c;神…

qt QListView详解

1、概述 QListView 是 Qt 框架中的一个视图类&#xff0c;用于展示模型中的数据。它基于 QAbstractItemView&#xff0c;支持多种视图模式&#xff0c;如列表视图&#xff08;List View&#xff09;、图标视图&#xff08;Icon View&#xff09;等。QListView 是模型/视图框架…

【MySQL】数据库整合攻略 :表操作技巧与详解

前言&#xff1a;本节内容讲述表的操作&#xff0c; 对表结构的操作。 是对表结构中的字段的增删查改以及表本身的创建以及删除。 ps&#xff1a;本节内容本节内容适合安装了MySQL的友友们进行观看&#xff0c; 实操更有利于记住哦。 目录 创建表 查看表结构 修改表结构 …

图片搜索引擎,来快速实现一个高性能的本地图片搜索引擎

文章来自&#xff1a;苏洋博客 以及基于 Redis 来快速实现一个高性能的本地图片搜索引擎&#xff0c;在本地环境中&#xff0c;使用最慢的稠密向量检索方式来在一张万图片中查找你想要的图片&#xff0c;总花费时间都不到十分之一秒。 写在前面 Redis, 你这浓眉大眼的家伙也正…

DevOps-课堂笔记

各种 aaS 类比于计算机网络的 OSI 参考模型&#xff0c;一个软件应用项目需要不同的支撑层&#xff0c;例如从下至上大概需要&#xff1a; 硬件层面的服务器针对硬件做弹性分配的虚拟化机制&#xff0c;例如虚拟机在虚拟化环境内运行的 OS支撑软件应用的中间件&#xff0c;例…

边缘计算的学习

文章目录 概要何为边缘计算&#xff1f;现阶段&#xff0c;企业使用边缘计算相对云计算 整体架构流程边缘网络组件边缘计算与云安全 研究方向结合引用 概要 edge 何为边缘计算&#xff1f; 边缘计算&#xff08;英语&#xff1a;Edge computing&#xff09;&#xff0c;是一种…

Spring Boot实现文件上传与OSS集成:从基础到应用

目录 前言1. 文件上传的基础实现1.1 前端文件上传请求1.2 后端文件接收与保存 2. 集成第三方OSS服务2.1 准备工作2.2 编写OSS集成代码2.3 修改Controller实现文件上传至OSS 3. 文件上传的扩展&#xff1a;多文件上传与权限控制结语 前言 随着互联网应用的快速发展&#xff0c;…

万字长文解读深度学习——卷积神经网络CNN

推荐阅读&#xff1a; 卷积神经网络&#xff08;CNN&#xff09;详细介绍及其原理详解 CNN笔记&#xff1a;通俗理解卷积神经网络 文章目录 &#x1f33a;深度学习面试八股汇总&#x1f33a;主要组件输入层卷积层 (Convolutional Layer)批归一化层&#xff08;Batch Normalizat…

07 Oracle数据库恢复基础解析:从检查点到归档,一步步构建数据安全防线

文章目录 Oracle数据库恢复基础解析&#xff1a;从检查点到归档&#xff0c;一步步构建数据安全防线一、检查点&#xff08;Checkpoint&#xff09;1.1 检查点定义1.2 检查点重要性1.3 检查点工作原理1.4 手动触发检查点 二、日志&#xff08;Redo Log&#xff09;2.1 日志定义…

css | padding vs margin

前置知识 height是作用域内容(content)区域的 padding和margin用百分比的时候是怎么算的&#xff1f;父元素的宽度。注意&#xff0c;不是根据父元素相应的属性&#xff0c;就是父亲的width 自身的height是0 以下代码&#xff0c;外面盒子是100x10的&#xff0c;里面的widt…

Linux平台C99与C++11获取系统时间

源码: #include <iostream> #include <chrono> #include <ctime> #include <thread>using namespace std; int main() {cout << "===使用C99方式获取系统时间===" << endl;time_t now = time(nullptr);struct tm *tm_c99 = lo…

pwn学习笔记(11)--off_by_one

pwn学习笔记&#xff08;11&#xff09;–off_by_one ​ 在处理for循环或者while循环的时候&#xff0c;有的可能会遇到如下情况&#xff1a; #include<stdio.h>int main(){char buf[0x10];for (int i 0 ; i < 0x10 ; i ){buf[i] getchar();}puts(buf);}​ 多次输…

基于Java Web的传智播客crm企业管理系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…