设计模式-享元模式

简介

享元模式(Flyweight Pattern)是一种用于效率和内存优化的结构型设计模式。这种模式通过共享尽可能多的相似对象来减少内存使用,特别适合于处理大量对象时,每个对象都消耗大量内存的场景

享元模式的核心思想

享元模式的核心在于分离变与不变。它将对象信息分为两个部分:

  • 内部状态(Intrinsic State):不依赖于场景,且不会改变的数据。
  • 外部状态(Extrinsic State):依赖于场景,并且会改变的数据。

内部状态存储在享元对象内部,通常不会改变,而外部状态则可以从外部传入享元对象来改变其行为。通过这种方式,可以使用相对较少的共享对象来替代大量的对象

使用场景

  • 大量相似对象的创建需要消耗大量的内存。
  • 对象的大多数状态都可以外部化,可以被多个对象共享。
  • 应用程序不依赖于对象标识。由于享元对象可以被共享,因此对于标识敏感的应用,享元模式可能不适用。

示例实现

假设我们正在开发一个游戏,其中有成千上万的树木。每棵树都有其位置、形状和颜色等属性。其中,形状和颜色是内部状态,因为它们在多个树之间可以共享。位置是外部状态,每棵树的位置都是独特的。

  • 首先定义树的享元对象

    javascript 复制代码
    // 享元对象
    class TreeType {
        constructor(name, color, texture) {
            this.name = name;
            this.color = color;
            this.texture = texture;
        }
    
        display(location) {
            console.log(`Displaying a ${this.color} ${this.name} at ${location.x}, ${location.y}`);
        }
    }
    
    // 享元工厂
    class TreeFactory {
        static treeTypes = new Map();
    
        static getTreeType(name, color, texture) {
            const key = `${name}_${color}_${texture}`;
            if (!this.treeTypes.has(key)) {
                this.treeTypes.set(key, new TreeType(name, color, texture));
                console.log('Creating a new TreeType object');
            }
            return this.treeTypes.get(key);
        }
    }

    然后是管理树木的类,它使用享元对象:

    javascript 复制代码
    class Tree {
        constructor(x, y, treeType) {
            this.x = x;
            this.y = y;
            this.treeType = treeType;
        }
    
        display() {
            this.treeType.display({ x: this.x, y: this.y });
        }
    }
    
    class Forest {
        constructor() {
            this.trees = [];
        }
    
        plantTree(x, y, name, color, texture) {
            const type = TreeFactory.getTreeType(name, color, texture);
            const tree = new Tree(x, y, type);
            this.trees.push(tree);
        }
    
        displayForest() {
            this.trees.forEach(tree => tree.display());
        }
    }

    使用这些类:

    javascript 复制代码
    const forest = new Forest();
    forest.plantTree(1, 2, 'Maple', 'Red', 'Smooth');
    forest.plantTree(5, 3, 'Maple', 'Red', 'Smooth');
    forest.plantTree(8, 2, 'Oak', 'Green', 'Rough');
    forest.displayForest();

优点

  • 内存节省:享元模式可以极大地减少程序所需的对象数量,从而降低内存消耗。
  • 提高性能:减少实例化对象的数量减轻了内存的压力,提高了应用性能。

缺点

  • 复杂度增加:需要区分内部状态和外部状态,管理共享对象,增加了实现的复杂度。
  • 线程安全问题:在多线程环境下,若共享对象的内部状态被外部状态改变,可能会导致线程安全问题。

总结

总的来说,享元模式在处理大量相似对象时提供了一种有效的内存优化策略。然而,它的使用应当谨慎,需要正确评估和设计内部状态和外部状态,以确保不会对应用程序的逻辑造成负面影响。在 JavaScript 等动态语言中,享元模式可以帮助管理内存消耗,尤其是在客户端浏览器环境中,这对提升用户体验和应用性能都是非常有益的。

相关推荐
ttod_qzstudio2 小时前
【软考设计模式】策略模式:算法族的封装与动态切换精讲
设计模式·策略模式
咖啡八杯10 小时前
GoF设计模式——迭代器模式
java·后端·设计模式·迭代器模式
ttod_qzstudio11 小时前
【软考设计模式】外观模式:复杂子系统的“门面“封装与代码填空精讲
设计模式·外观模式
geovindu18 小时前
CSharp: Prototype Pattern
开发语言·后端·设计模式·.net·原型模式·创建型模式
ttod_qzstudio18 小时前
【软考设计模式】组合模式:“部分-整体“层次结构与树形对象统一操作精讲
设计模式·组合模式
ttod_qzstudio20 小时前
【软考设计模式】装饰模式:“套娃“式增强与动态职责扩展精讲
设计模式·装饰模式
烬羽21 小时前
MCP 多服务器架构实战:一个 Agent 同时操控地图、浏览器和文件
设计模式·设计
阿pin1 天前
Android随笔-常用的设计模式
android·设计模式
儒雅的名1 天前
GoF设计模式——策略模式
设计模式·bash·策略模式
折哥的程序人生 · 物流技术专研1 天前
第4篇:Lambda 简化策略模式(Java 8+)
java·设计模式·策略模式·函数式编程·lambda·代码简化·扩充系列