首页 > 其他分享 >享元模式

享元模式

时间:2024-02-28 15:37:24浏览次数:18  
标签:享元 状态 对象 创建 模式 图像 共享

简介

享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享对象来减少内存使用和提高性能。它适用于需要大量相似对象的情况,其中对象的大部分状态都可以共享,而少部分状态需要外部化。通过共享这些相似对象,可以减少内存消耗,提高系统性能。

结构

  • 享元工厂(Flyweight Factory):负责创建和管理享元对象。它维护一个享元池(Flyweight Pool),用于存储已经创建的享元对象,当需要时,从中返回已存在的对象,而不是重新创建。

  • 享元(Flyweight):表示一个可以被共享的对象。享元对象包含内部状态(Intrinsic State)和外部状态(Extrinsic State):

    • 内部状态是可以被共享的,它存储在享元对象内部,不随环境改变而改变。
    • 外部状态是不可共享的,它取决于享元对象的使用环境,因此需要在外部单独维护

案例

 考虑一个图像编辑器应用程序,其中可能需要处理大量相似的图像对象,例如图标、按钮、背景等。这些图像对象通常具有一些共享的特性,比如相同的尺寸、颜色、形状等,这些特性可以看作是图像的内部状态。而每个图像对象可能还有自己的一些属性,比如位置、旋转角度、透明度等,这些属性则可以看作是图像的外部状态。

在这种情况下,可以使用享元模式来优化图像对象的管理:

  • 享元工厂:图像管理器充当享元工厂的角色,负责创建和管理图像对象。它维护一个图像池,存储已经创建的图像对象。

  • 图像对象:每个图像对象都是一个享元对象,包含共享的内部状态(如尺寸、颜色等)和独立的外部状态(如位置、旋转角度等)。

通过使用享元模式,图像编辑器可以实现以下好处:

  1. 减少内存占用:相似的图像对象可以共享相同的内部状态,从而减少内存占用。

  2. 提高性能:减少了重复对象的创建和销毁,提高了系统的性能。

  3. 灵活管理:每个图像对象的外部状态可以独立管理,使得系统能够灵活地处理每个图像对象的属性变化,如位置、旋转等操作。

通过这种方式,图像编辑器可以更高效地管理大量的图像对象,并提高系统的性能和可维护性。

下面是一个简单的使用 C# 实现享元模式的示例,模拟图像编辑器应用程序中的图像管理:  
using System;
using System.Collections.Generic;

// 享元接口,定义了图像对象的操作方法
interface IImage
{
    void Draw(int x, int y);
}

// 具体享元类,实现了享元接口,表示具体的图像对象
class Image : IImage
{
    private string name;
    private int width;
    private int height;

    public Image(string name, int width, int height)
    {
        this.name = name;
        this.width = width;
        this.height = height;
    }

    public void Draw(int x, int y)
    {
        Console.WriteLine($"Drawing image {name} at position ({x}, {y}) with size {width}x{height}");
    }
}

// 享元工厂,负责创建和管理享元对象
class ImageFactory
{
    private Dictionary<string, Image> images = new Dictionary<string, Image>();

    public IImage GetImage(string name, int width, int height)
    {
        string key = $"{name}-{width}-{height}";
        if (!images.ContainsKey(key))
        {
            images[key] = new Image(name, width, height);
        }
        return images[key];
    }
}

class Program
{
    static void Main(string[] args)
    {
        ImageFactory imageFactory = new ImageFactory();

        // 从享元工厂获取图像对象
        IImage image1 = imageFactory.GetImage("icon", 100, 100);
        IImage image2 = imageFactory.GetImage("icon", 100, 100);
        IImage image3 = imageFactory.GetImage("background", 800, 600);

        // 绘制图像
        image1.Draw(10, 10);
        image2.Draw(20, 20);
        image3.Draw(0, 0);

        // 检查是否为同一对象
        Console.WriteLine($"Is image1 the same as image2? {ReferenceEquals(image1, image2)}"); // True
        Console.WriteLine($"Is image1 the same as image3? {ReferenceEquals(image1, image3)}"); // False
    }
}

在这个示例中,Image 类表示具体的图像对象,实现了 IImage 接口。ImageFactory 类是享元工厂,负责创建和管理图像对象。在 Main 方法中,我们使用工厂获取图像对象,并展示了图像的绘制过程。

其他案例

  1. 数据库连接池:在 ASP.NET 应用中,数据库连接池可以被看作一种享元模式的应用。连接池管理着一组数据库连接对象,这些连接对象的创建和销毁开销较大。当需要执行数据库操作时,可以从连接池中获取连接对象,并在使用完毕后将其放回连接池,以便其他请求共享使用。

  2. 缓存管理:在 ASP.NET 应用中,缓存管理也可以被看作一种享元模式的应用。缓存管理器管理着一组缓存对象,这些对象的创建和销毁开销较大。当需要读取缓存数据时,可以从缓存管理器中获取缓存对象,并在使用完毕后将其放回管理器,以便其他请求共享使用。

  3. 字符串池:在 .NET 中,字符串池是一种常见的优化机制,它会对相同的字符串进行共享,以减少内存消耗和提高性能。这种机制与享元模式的概念相似,都是通过共享对象来减少内存使用。

优点

  1. 减少内存使用:通过共享相同的对象实例,可以大大减少系统中对象的数量,从而减少内存使用。

  2. 提高性能:减少了对象的创建和销毁次数,可以大大提高系统的性能。由于共享对象的创建是在工厂中完成的,因此客户端代码只需要获取对象即可,无需自行创建,减少了对象创建的时间和开销。

  3. 对象池化管理:享元模式提供了一个对象池,统一管理相同属性的对象,使得对象的创建和销毁过程更加可控和可管理。

缺点

  1. 复杂性增加:享元模式的实现可能需要引入额外的复杂性,特别是对于需要考虑对象的内部状态和外部状态的情况,需要仔细设计和管理对象的状态。

  2. 外部状态管理:当对象具有外部状态时,需要额外的逻辑来管理外部状态的变化,这可能会增加系统的复杂性。

  3. 可能引入线程安全问题:在多线程环境下,需要考虑对象的共享和同步问题,确保共享对象的线程安全性。

适用场景

  1. 大量相似对象的重复创建:当系统中存在大量相似对象,并且这些对象的大部分状态可以共享时,可以考虑使用享元模式。通过共享相同状态的对象,可以大大减少内存使用和提高性能。

  2. 对象的创建和销毁开销较大:当对象的创建和销毁开销较大,且需要频繁地创建和销毁对象时,可以考虑使用享元模式。通过对象池管理共享对象,可以避免频繁地创建和销毁对象,提高系统的性能。

  3. 对象具有内部状态和外部状态:当对象具有内部状态和外部状态,并且外部状态相对固定,而内部状态可以共享时,可以考虑使用享元模式。通过将外部状态作为享元对象的参数传入,可以实现内部状态共享,外部状态独立的效果。

  4. 需要缓存共享对象以提高性能:当系统需要缓存共享对象以提高性能时,可以考虑使用享元模式。通过享元工厂管理共享对象的缓存,可以避免重复创建对象,提高系统的性能。

  5. 系统需要动态管理对象的数量:当系统需要动态管理对象的数量,并且需要灵活控制对象的创建和销毁时,可以考虑使用享元模式。通过对象池管理共享对象,可以动态地调整对象的数量,提高系统的灵活性和可维护性。

标签:享元,状态,对象,创建,模式,图像,共享
From: https://www.cnblogs.com/mchao/p/18040400

相关文章

  • 装饰器模式
    简介装饰器模式(DecoratorPattern)是一种结构型设计模式,它允许向现有对象动态地添加新功能,同时又不改变其结构。该模式通过创建一个包装对象,也就是装饰器,来包裹原始对象,并在包裹的过程中添加新的行为或责任。结构Component(组件):定义了一个对象接口,可以给这些对象动态地添加职责......
  • 组合模式
    简介组合模式是一种结构型设计模式,它允许你将对象组合成树形结构以表现"部分-整体"的层次结构。这种模式使得用户对单个对象和组合对象的使用具有一致性。在组合模式中,有两种主要类型的对象:叶节点和组合节点。叶节点代表了树结构中的最终对象,而组合节点则表示了可以包含其他组合......
  • 桥接模式
    简介桥接模式(BridgePattern)是一种结构型设计模式,它主要用于将抽象部分与实现部分分离,从而使它们可以独立变化。桥接模式通过将继承关系转化为组合关系,使得抽象部分和实现部分可以独立地变化,不会相互影响。在桥接模式中,抽象部分通常指的是一个抽象类或接口,它定义了对外的接口或......
  • KISS 原则 (设计模式)
    KISS定义kiss原则的英文描述又几个版本,计较下边的这几个keepitsimpleandstupid.keepitshortandsimplekeepitsimpleandstraightforward不过仔细看你会发现,他们表达的意思其实差不多,尽量保持简单。它是一个万金油的设计原则,可以在很多场景中,它不仅仅经常用来指......
  • 适配器模式
    简介适配器模式是一种结构型设计模式,它允许将一个类的接口转换成客户端所期望的另一个接口。适配器模式通常用于解决两个不兼容接口之间的兼容性问题,使得原本由于接口不匹配而无法一起工作的类能够协同工作。适配器模式主要由三个角色组成:目标接口(TargetInterface):客户端所期......
  • 原型模式
    定义:原型模式(PrototypeDesignPattern)用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象原型模式主要解决的问题: 如果创建对象的成本较大,比如对象中的数据是经过复杂计算才能得到的,或者需要从RPC接口或者数据库等比较慢的IO中获取,这种情况我们......
  • 原型模式
    简介原型模式(PrototypePattern)是一种创建型设计模式,它允许创建新对象的同时,通过复制现有对象的方式来初始化新对象。这意味着在原型模式中,新对象的创建过程不再依赖于直接实例化类,而是通过复制已有对象的方式来进行。在原型模式中,存在一个原型对象(Prototype),它是需要被复制的对......
  • 建造者模式
    简介建造者模式(BuilderPattern)是一种创建型设计模式,用于构建复杂对象。它的主要目的是将对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示形式。这种模式通常适用于创建对象的参数较多,且某些参数之间存在复杂的依赖关系的情况。在建造者模式中,通常会有一个建造......
  • C++特殊类的设计与单例模式
    //1.设计一个不能被拷贝的类/*解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。C++98;将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即......
  • 详解在 centos 中引导到救援模式
    详解在centos中引导到救援模式Linux系统CentOS进入单用户模式和救援模式详解一、概述目前在运维日常工作中,经常会遇到服务器异常断电、忘记root密码、系统引导文件损坏无法进入系统等等操作系统层面的问题,给运维带来诸多不便,现将上述现象的解决方法和大家分享一下,本次主要以C......