首页 > 编程语言 >Flyweight 享元模式简介与 C# 示例【结构型6】【设计模式来了_11】

Flyweight 享元模式简介与 C# 示例【结构型6】【设计模式来了_11】

时间:2023-11-01 20:11:05浏览次数:29  
标签:享元 flyweight 示例 对象 模式 Flyweight 共享 设计模式

〇、简介

1、什么是享元模式?

一句话解释:

  将相似或同类的对象共享同一个对象,将这些对象暂存在列表中,使用时直接取出,避免每次使用时都要新建浪费资源。

享元模式的目的是减少对象的创建,通过共享对象来提高系统的性能。享元设计模式将对象的实例分为两种:内部共享对象和外部共享对象。内部共享对象是由享元类创建的,可以被多个对象共享。外部共享对象是由客户端创建的,不能被多个对象共享。

官方意图描述:运用共享技术有效地支持大量细粒度的对象。

一个比喻:(学校的足球场和篮球馆)

  首先对于学校的足球场和篮球馆有共享属性,当有足球比赛时,就对应的是足球场,有篮球比赛时,对应的就是篮球馆,不会每次比赛都去新建场馆。

2、享元模式的优缺点和适用场景

优点:

  • 减少对象的创建:享元设计模式通过共享对象来减少对象的创建,这样可以减少内存占用从而提高系统的性能。
  • 简化客户端代码:客户端只需要与享元接口交互,而不需要了解底层的具体实现细节,从而简化了客户端的代码。
  • 提高系统的扩展性:享元设计模式通过共享对象来提高系统的扩展性,这样可以方便地添加新的共享对象。
  • 降低系统的耦合度:享元模式将对象的创建和使用分离开来,使得系统的各个部分之间的耦合度降低,提高了系统的可维护性和可扩展性。

缺点:

  • 增加了系统的复杂性:享元模式需要引入额外的享元工厂类和享元类,增加了系统的复杂性。
  • 可能增加系统的维护成本:享元模式可能会增加系统的维护成本,因为需要考虑如何更新对象、如何维护对象、如何测试对象等问题。
  • 影响系统的稳定性:当新增类型时,需要对享元工厂进行修改,可能导致系统的异常,同时也会增加额外的维护成本。

适用场景:

  • 对象池:当需要频繁创建和销毁相似的对象时,可以使用享元模式将这些对象缓存在一个池中,以便重复使用。这样可以减少对象的创建和销毁成本,提高性能。
  • 文字编辑器:在文字编辑器中,每个字符都可以作为一个独立的对象来表示。但对于相同的字符,我们不必为每个出现的位置都创建一个新对象,而是可以共享同一个对象实例,从而节省内存空间。
  • 缓存系统:在缓存系统中,经常需要缓存大量的数据对象。通过使用享元模式,可以共享相同的数据对象,减少内存占用,并提高缓存的效率。
  • 游戏开发:在游戏中,特别是大规模多人在线游戏(MMOG)中,存在大量相似的对象,如玩家、怪物、道具等。通过使用享元模式,可以共享这些相似对象之间的公共数据,并且只需存储各个对象的变化部分,从而节省内存占用。

一、通过简单的示例代码实现享元模式

如下示例代码,通过一个字典来存储类的实例,如果 key 标识的实例第二次调用时,就直接从字典中取,不再重新创建:

// 测试一下
class Program
{
    static void Main(string[] args)
    {
        Flyweight flyweight = FlyweightFactory.GetFlyweight("Flyweight");
        Flyweight flyweight1 = FlyweightFactory.GetFlyweight("Flyweight1");
        Flyweight flyweight2 = FlyweightFactory.GetFlyweight("Flyweight2");
        flyweight.Operation();
        flyweight1.Operation();
        flyweight2.Operation();
        Console.ReadLine();
    }
}
public class FlyweightFactory
{
    private static Dictionary<string, Flyweight> flyweightDictionary = new Dictionary<string, Flyweight>();
    public static Flyweight GetFlyweight(string key)
    {
        if (flyweightDictionary.ContainsKey(key))
        {
            return flyweightDictionary[key];
        }
        else
        {
            switch (key) 
            {
                case "Flyweight1":
                    ConcreteFlyweight1 flyweight1 = new ConcreteFlyweight1();
                    flyweightDictionary[key] = flyweight1;
                    return flyweight1;
                case "Flyweight2":
                    ConcreteFlyweight2 flyweight2 = new ConcreteFlyweight2();
                    flyweightDictionary[key] = flyweight2;
                    return flyweight2;
                default:
                    Flyweight flyweight = new Flyweight();
                    flyweightDictionary[key] = flyweight;
                    return flyweight;
            }
        }
    }
}
public class Flyweight
{
    public virtual void Operation()
    {
        Console.WriteLine("Operation is performed by Flyweight.");
    }
}
public class ConcreteFlyweight1 : Flyweight
{
    public override void Operation()
    {
        Console.WriteLine("ConcreteFlyweight1 is performing the operation.");
    }
}
public class ConcreteFlyweight2 : Flyweight
{
    public override void Operation()
    {
        Console.WriteLine("ConcreteFlyweight2 is performing the operation.");
    }
}

若后续需要添加新的享元实例ConcreteFlyweight3,就可以直接继承类Flyweight,但同时也需要在FlyweightFactory工厂类中添加对应的实例判断代码。

二、结构

根据上一章节中的示例代码,可以得结构图:

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

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

FlyweightFactory:创建并管理flyweight 对象;确保合理地共享 flyweight。当用户请求一个 flyweight 时,FlyweightFactory 对象提供一个已创建的实例或者创建一个(如果不存在的话)。

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

三、相关模式

Flyweight 享元模式通常和 Composite 组合模式结合起来,用共享叶结点的有向无环图实现一个逻辑上的层次结构。

通常,最好用 flyweight 实现 State 状态模式和Strategy 策略模式对象。

标签:享元,flyweight,示例,对象,模式,Flyweight,共享,设计模式
From: https://www.cnblogs.com/hnzhengfy/p/SJMSLL_FlyWeight.html

相关文章

  • 使用phpQuery库采集平安健康代码示例
    大家好,今天给大家分享的内容是使用phpQuery库采集平安健康相关视频,内容非常简单,篇幅也很短,但是确实很实用,一起学习一下吧。```php<?php//引入phpQuery库require_once'phpQuery/phpQuery.php';//创建一个phpQuery对象$jq=phpQuery::newDocument();//使用配置p......
  • 创建一个Web服务器并保持其运行,可以使用Python的Flask库。以下是一个基本的示例: ```p
    创建一个Web服务器并保持其运行,可以使用Python的Flask库。以下是一个基本的示例:```pythonfromflaskimportFlask,requestimportosapp=Flask(__name__)@app.route('/webhook',methods=['POST'])defwebhook():  data=request.get_json()  #在这里添加你的......
  • 设计模式(Design Pattern)记忆
    创建型记忆口诀:创公园,但见愁创工原,单建抽创建型工厂方法FactoryMethod原型Prototype单例Singleton建造者Builder抽象工厂AbstractFactory结构型记忆口口诀:姐想外祖,世代装桥结享外组,适代装桥结构型:享元Flyweight外观Facade组合Composite适配器Adapter装饰Decorat......
  • c#享元模式详解
    基本介绍:  享元模式的定义:运用共享技术有效地支持大量细粒度的对象重复使用。适用于大量小粒度的对象造成的运行效率和内存使用效率低下的情况。  “享元”顾名思义,“享”共享的意思,“元”单元,最小对象,零部件的意思。  即从字面意思不难看出,该模式旨在共享一些零部件供其......
  • Android自动化测试框架:UiAutomator和UiAutomator2的区别与示例代码
    UiAutomator和UiAutomator2是两种常用的Android自动化测试框架,它们都是由Google开发的。然而,它们之间存在一些关键的区别:API级别:UiAutomator框架在Android4.3(API级别18)中引入,而UiAutomator2在Android5.0(API级别21)中引入。测试能力:UiAutomator只能测试Android系统应用......
  • Linux时间校准、时间同步(ntpdate及C代码NTP客户端代码校准示例)
    背景机器每次机启后时间就会出现异常,因为机器无法访问外网,只能访问局域网的ntp服务,所以需要保证局域网内部有ntp服务,如何安装ntp服务,参考Ubuntu20.04Ntp服务安装及验证。网络时间协议NetworkTimeProtocol(NTP)是一种确保时钟保持准确的方法。如果可以访问互联网,只需安装ntp......
  • huatuo热更环境安装与示例项目
    上一节我们分析了huatuo的原理与优势,相信大家迫不及待想体验一下huatuo热更新,本节我们来安装huatuo的开发环境,然后运行示例项目,来体验下huatuo做热更新。huatuo 热更开发环境的安装使用huatuo之前,我们先准备好开发环境,Unity版本,官方的huatuo版本采用的是unity2020.3.33f1的......
  • 大话设计模式之装饰模式笔记
    装饰模式的基本结构classDiagramclassComponent{<<interface>>+operation();}classConcreateComponent{+operation();}classDecrator{-Componentcomponent;+operation();}class......
  • 设计模式-中介者模式
    publicclass中介者模式{publicstaticvoidmain(String[]args){Mediatormediator=newConcreteMediator();ColleagueAcolleagueA=newColleagueA(mediator);ColleagueBcolleagueB=newColleagueB(mediator);mediator.setC......
  • 设计模式-访问者模式
    importjava.util.ArrayList;importjava.util.List;publicclass访问者结构{publicstaticvoidmain(String[]args){Visitvisit1=newVisitA();Visitvisit2=newVisitB();PersonStructurepersonStructure=newPersonStructure()......