设计模式-09 - 享元模式 flyweight pattern

2024-05-12 08:36

本文主要是介绍设计模式-09 - 享元模式 flyweight pattern,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

设计模式-09 - 享元模式  flyweight pattern

1.定义

享元模式是一种设计模式,它使用共享对象来减少内存使用和提高性能。它通过存储共享的对象实例池来实现,这些实例可以被多个客户端同时使用。

享元模式定义了一个接口,使客户端可以访问共享的轻量级对象。享元可以根据其内部状态进行细分,客户端只需要提供它需要的状态即可。享元对象被存储在共享池中,如果客户端请求一个已经存在的享元,则会返回该享元,否则会创建一个新的享元并将其添加到池中。

+--------------------+| Flyweight Factory  |+--------------------+|+--------------------+| Concrete Flyweight |+--------------------+|                    ||                    ||                    ||                    |+--------------------+|+--------------------------+| Context (with Flyweight) |+--------------------------+

说明:

  • Flyweight Factory:创建和管理享元对象。
  • Concrete Flyweight:实现享元接口的具体对象。享元对象是轻量级的、不可变的,并且具有大量重复实例。
  • Context:使用享元对象,并为其提供外部状态。
2.内涵

享元模式通常用于以下场景:

  • 当需要大量相同或相似对象时,例如在图形应用程序中表示图像或文本。
  • 当对象状态存储在外部数据结构中时,例如在数据库或缓存中。
  • 当对象创建或销毁成本很高时。

一个常见的享元模式示例是字符集中的字符对象。每个字符都可以表示为享元对象,其状态是字符的外观。当需要显示文本时,应用程序可以请求字符享元,而不需要为每个字符创建一个单独的对象。

享元模式与其他设计模式有一些相似之处:

  • 单例模式:享元模式与单例模式类似,因为它创建了一个共享对象,但享元模式允许创建多个共享对象。
  • 工厂方法模式:享元模式可以使用工厂方法模式来创建共享对象。
  • 策略模式:享元模式可以使用策略模式来存储对象的内部状态。

3.使用示例
#include <iostream>
#include <unordered_map>// Flyweight class
class Character {
public:Character(char intrinsicState) : m_intrinsicState(intrinsicState) {}void draw(int extrinsicState) {std::cout << "Drawing character '" << m_intrinsicState << "' at position " << extrinsicState << std::endl;}private:char m_intrinsicState;
};// Flyweight factory
class CharacterFactory {
public:Character* getCharacter(char key) {if (m_characters.find(key) == m_characters.end()) {m_characters[key] = new Character(key);}return m_characters[key];}private:std::unordered_map<char, Character*> m_characters;
};int main() {CharacterFactory characterFactory;// Extrinsic stateint position = 0;// Drawing characters 'A', 'B', 'C' at different positionscharacterFactory.getCharacter('A')->draw(position++);characterFactory.getCharacter('B')->draw(position++);characterFactory.getCharacter('C')->draw(position++);return 0;
}

4.注意事项


在使用享元模式时,需要注意以下事项:

  • 确定可共享的对象:并非所有对象都适合共享。只有当对象是轻量级的、不可变的并且具有大量重复实例时,才应考虑使用享元模式。
  • 管理对象状态:享元对象必须是不可变的,这意味着它们的状态一旦创建就不能被改变。如果对象需要可变状态,则可能需要使用其他设计模式,例如策略模式。
  • 处理并发性:如果多个客户端同时访问享元对象,则需要考虑并发性问题。可以使用同步机制来确保对象状态的一致性。
  • 避免过度共享:虽然共享对象可以减少内存使用,但过度共享可能会导致性能下降。只应共享真正需要的对象。
  • 考虑代码复杂性:享元模式可以引入一些代码复杂性,因为它需要管理共享对象池。在使用享元模式之前,应权衡收益和成本。
  • 其他注意事项:
  • 对象识别:享元对象需要一种方法来被客户端识别。这通常是通过使用唯一标识符或其他属性来实现的。
  • 外部状态:享元对象可以存储外部状态,但该状态不应修改享元对象本身。
  • 性能优化:为了优化享元模式的性能,应使用对象池来管理共享对象。对象池可以减少创建和销毁对象的开销。
  • 可测试性:享元模式的实现应可测试,以验证共享对象的正确性。可以使用单元测试来验证对象池的功能和共享对象的不可变性。
5.最佳实践


 
享元模式(Flyweight Pattern)最佳实践

1. 仅对可共享对象使用享元:

享元对象应是轻量级的、不可变的,并且具有大量重复实例。
2. 使用对象池管理共享对象:

对象池可以减少创建和销毁对象的开销,从而提高性能。
3. 确保对象不可变性:

享元对象的状态一旦创建就不能被改变。
4. 考虑并发性:

如果多个客户端同时访问享元对象,则需要考虑并发性问题。可以使用同步机制来确保对象状态的一致性。
5. 避免过度共享:

只应共享真正需要的对象。过度共享可能会导致性能下降。
6. 使用唯一标识符识别对象:

享元对象需要一种方法来被客户端识别。这通常是通过使用唯一标识符或其他属性来实现的。
7. 将外部状态存储在其他对象中:

享元对象可以存储外部状态,但该状态不应修改享元对象本身。
8. 使用单元测试验证共享对象的正确性:

单元测试可以验证对象池的功能和共享对象的不可变性。


6.总结


在使用享元模式时,应遵循设计原则,例如单一职责原则、开放/封闭原则和里氏替换原则。
通过遵循这些最佳实践,可以有效地使用享元模式来提高应用程序的性能和可维护性。

这篇关于设计模式-09 - 享元模式 flyweight pattern的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/982128

相关文章

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

模版方法模式template method

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/template-method 超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 上层接口有默认实现的方法和子类需要自己实现的方法

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

迭代器模式iterator

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/iterator 不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素

Java第二阶段---09类和对象---第三节 构造方法

第三节 构造方法 1.概念 构造方法是一种特殊的方法,主要用于创建对象以及完成对象的属性初始化操作。构造方法不能被对象调用。 2.语法 //[]中内容可有可无 访问修饰符 类名([参数列表]){ } 3.示例 public class Car {     //车特征(属性)     public String name;//车名   可以直接拿来用 说明它有初始值     pu

《x86汇编语言:从实模式到保护模式》视频来了

《x86汇编语言:从实模式到保护模式》视频来了 很多朋友留言,说我的专栏《x86汇编语言:从实模式到保护模式》写得很详细,还有的朋友希望我能写得更细,最好是覆盖全书的所有章节。 毕竟我不是作者,只有作者的解读才是最权威的。 当初我学习这本书的时候,只能靠自己摸索,网上搜不到什么好资源。 如果你正在学这本书或者汇编语言,那你有福气了。 本书作者李忠老师,以此书为蓝本,录制了全套视频。 试

利用命令模式构建高效的手游后端架构

在现代手游开发中,后端架构的设计对于支持高并发、快速迭代和复杂游戏逻辑至关重要。命令模式作为一种行为设计模式,可以有效地解耦请求的发起者与接收者,提升系统的可维护性和扩展性。本文将深入探讨如何利用命令模式构建一个强大且灵活的手游后端架构。 1. 命令模式的概念与优势 命令模式通过将请求封装为对象,使得请求的发起者和接收者之间的耦合度降低。这种模式的主要优势包括: 解耦请求发起者与处理者

springboot实战学习(1)(开发模式与环境)

目录 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 (3)前端 二、开发模式 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 Validation:做参数校验Mybatis:做数据库的操作Redis:做缓存Junit:单元测试项目部署:springboot项目部署相关的知识 (3)前端 Vite:Vue项目的脚手架Router:路由Pina:状态管理Eleme

状态模式state

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/state 在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。 在状态模式中,player.getState()获取的是player的当前状态,通常是一个实现了状态接口的对象。 onPlay()是状态模式中定义的一个方法,不同状态下(例如“正在播放”、“暂停

软件架构模式:5 分钟阅读

原文: https://orkhanscience.medium.com/software-architecture-patterns-5-mins-read-e9e3c8eb47d2 软件架构模式:5 分钟阅读 当有人潜入软件工程世界时,有一天他需要学习软件架构模式的基础知识。当我刚接触编码时,我不知道从哪里获得简要介绍现有架构模式的资源,这样它就不会太详细和混乱,而是非常抽象和易