`
qzriso
  • 浏览: 242637 次
  • 性别: Icon_minigender_1
  • 来自: ph
社区版块
存档分类
最新评论

设计模式之享元模式

阅读更多

一、 享元(Flyweight)模式(转贴)

Flyweight在拳击比赛中指最轻量级,即"蝇量级",有些作者翻译为"羽量级"。这里使用"享元模式"更能反映模式的用意。

享元模式以共享的方式高效地支持大量的细粒度对象。享元对象能做到共享的关键是区分内蕴状态(Internal State)和外蕴状态(External State)。内蕴状态是存储在享元对象内部并且不会随环境改变而改变。因此内蕴状态并可以共享。

外蕴状态是随环境改变而改变的、不可以共享的状态。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。外蕴状态与内蕴状态是相互独立的。

享元模式的应用

享元模式在编辑器系统中大量使用。一个文本编辑器往往会提供很多种字体,而通常的做法就是将每一个字母做成一个享元对象。享元对象的内蕴状态就是这 个字母,而字母在文本中的位置和字模风格等其他信息则是外蕴状态。比如,字母a可能出现在文本的很多地方,虽然这些字母a的位置和字模风格不同,但是所有 这些地方使用的都是同一个字母对象。这样一来,字母对象就可以在整个系统中共享。


二、 单纯享元模式的结构

在单纯享元模式中,所有的享元对象都是可以共享的。单纯享元模式所涉及的角色如下:

抽象享元(Flyweight)角色:此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口。那些需要外蕴状态(External State)的操作可以通过调用商业方法以参数形式传入。

具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。享元对象的内蕴状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享的。

享元工厂(FlyweightFactory)角色:本角色负责创建和管理享元角色。 本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个复合要求的享元对象。如 果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。

客户端(Client)角色:本角色需要维护一个对所有享元对象的引用。本角色需要自行存储所有享元对象的外蕴状态。


三、 单纯享元模式的示意性源代码

// Flyweight pattern -- Structural example  
using System;
using System.Collections;

// "FlyweightFactory"
class FlyweightFactory
{
  
// Fields
  private Hashtable flyweights = new Hashtable();

  
// Constructors
  public FlyweightFactory()
  
{
    flyweights.Add(
"X"new ConcreteFlyweight());
    flyweights.Add(
"Y"new ConcreteFlyweight());
    flyweights.Add(
"Z"new ConcreteFlyweight());
  }


  
// Methods
  public Flyweight GetFlyweight(string key)
  
{
    
return((Flyweight)flyweights[ key ]);
  }

}


// "Flyweight"
abstract class Flyweight
{
  
// Methods
  abstract public void Operation( int extrinsicstate );
}


// "ConcreteFlyweight"
class ConcreteFlyweight : Flyweight
{
  
private string intrinsicstate = "A";
  
// Methods
  override public void Operation( int extrinsicstate )
  
{
    Console.WriteLine(
"ConcreteFlyweight: intrinsicstate {0}, extrinsicstate {1}"
      intrinsicstate, extrinsicstate );
  }

}


/**//// <summary>
/// Client test
/// </summary>

public class Client
{
  
public static void Main( string[] args )
  
{
    
// Arbitrary extrisic state
    int extrinsicstate = 22;
     
    FlyweightFactory f 
= new FlyweightFactory();

    
// Work with different flyweight instances
    Flyweight fx = f.GetFlyweight("X");
    fx.Operation( 
--extrinsicstate );

    Flyweight fy 
= f.GetFlyweight("Y");
    fy.Operation( 
--extrinsicstate );

    Flyweight fz 
= f.GetFlyweight("Z");
    fz.Operation( 
--extrinsicstate );
  }

}


四、 复合享元模式的结构

单纯享元模式中,所有的享元对象都可以直接共享。下面考虑一个较为复杂的情况,即将一些单纯享元使用合成模式加以复合,形成复合享元对象。这样的复合享元对象本身不能共享,但是它们可以分解成单纯享元对象,而后者则可以共享。

复合享元模式的类图如下图所示:

享元模式所涉及的角色有抽象享元角色、具体享元角色、复合享元角色、享员工厂角色,以及客户端角色等。

抽象享元角色:此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口。那些需要外蕴状态(External State)的操作可以通过方法的参数传入。抽象享元的接口使得享元变得可能,但是并不强制子类实行共享,因此并非所有的享元对象都是可以共享的。

具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定的接 口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。享元对象的内蕴状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。有时候 具体享元角色又叫做单纯具体享元角色,因为复合享元角色是由单纯具体享元角色通过复合而成的。

复合享元(UnsharableFlyweight)角色:复合享元角色所代表的对象是不可以共享的,但是一个复合享元对象可以分解成为多个本身是单纯享元对象的组合。复合享元角色又称做不可共享的享元对象。

享元工厂(FlyweightFactoiy)角色:本角色负责创建和管理享元角色。 本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象请求一个享元对象的时候,享元工厂角色需要检查系统中是否已经有一个符合要求的享元对象, 如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个新的合适的享元对象。

客户端(Client)角色:本角色还需要自行存储所有享元对象的外蕴状态。

注:由于复合享元模式比较复杂,这里就不再给出示意性代码。通过将享元模式与合成模式组合在一起,可以确保复合享元中所包含的每个单纯享元都具有相同的外蕴状态,而这些单纯享元的内蕴状态往往不同。该部分内容可以参考《Java与模式》第31章内容。


五、 一个咖啡摊的例子

在这个咖啡摊(Coffee Stall)所使用的系统里,有一系列的咖啡"风味(Flavor)"。客人到摊位上购买咖啡,所有的咖啡均放在台子上,客人自己拿到咖啡后就离开摊位。 咖啡有内蕴状态,也就是咖啡的风味;咖啡没有环境因素,也就是说没有外蕴状态。如果系统为每一杯咖啡都创建一个独立的对象的话,那么就需要创建出很多的细 小对象来。这样就不如把咖啡按照种类(即"风味")划分,每一种风味的咖啡只创建一个对象,并实行共享。

使用咖啡摊主的语言来讲,所有的咖啡都可按"风味"划分成如Capucino、Espresso等,每一种风味的咖啡不论卖出多少杯,都是全同、不 可分辨的。所谓共享,就是咖啡风味的共享,制造方法的共享等。因此,享元模式对咖啡摊来说,就意味着不需要为每一份单独调制。摊主可以在需要时,一次性地 调制出足够一天出售的某一种风味的咖啡。

很显然,这里适合使用单纯享元模式。系统的设计如下:

using System;
using System.Collections;

public abstract class Order
{
  
// 将咖啡卖给客人
  public abstract void Serve();
  
// 返回咖啡的名字
  public abstract string GetFlavor();
}


public class Flavor : Order
{
  
private string flavor;

  
// 构造函数,内蕴状态以参数方式传入
  public Flavor(string flavor)
  
{
    
this.flavor = flavor;
  }


  
// 返回咖啡的名字
  public override string GetFlavor()
  
{
    
return this.flavor;
  }


  
// 将咖啡卖给客人
  public override void Serve()
  
{
    Console.WriteLine(
"Serving flavor " + flavor);
  }

}


public class FlavorFactory
{
  
private Hashtable flavors = new Hashtable();

  
public Order GetOrder(string key)
  
{
    
if(! flavors.ContainsKey(key))
      flavors.Add(key, 
new Flavor(key));

        
return ((Order)flavors[key]);
  }


  
public int GetTotalFlavorsMade()
  
{
    
return flavors.Count;
  }

}


public class Client
{
  
private static FlavorFactory flavorFactory;
  
private static int ordersMade = 0;

  
public static void Main( string[] args )
  
{
    flavorFactory 
= new FlavorFactory();

    TakeOrder(
"Black Coffee");
< SPAN>
分享到:
评论

相关推荐

    javascript 设计模式之享元模式原理与应用详解

    本文实例讲述了javascript 设计模式之享元模式。分享给大家供大家参考,具体如下: 享元模式说明 定义:用于解决一个系统大量细粒度对象的共享问题: 关健词:分离跟共享; 说明: 享元模式分单纯(共享)享元模式,...

    Java设计模式之享元模式

    享元模式是软件设计模式中的一种结构型模式,它的核心思想是通过共享已经存在的对象来减少内存中的对象数量,从而提高系统性能。在Java中,享元模式常用于处理大量相似对象的场景,例如在图形界面中绘制大量相似的...

    c++-设计模式之享元模式(Flyweight)

    享元模式(Flyweight Pattern)是一种结构型设计模式,用于减少创建大量小对象所带来的内存开销。通过共享对象,享元模式能够有效地支持大量细粒度的对象,减少内存使用并提高性能。它常用于需要大量重复对象的场景...

    23钟设计模式之享元模式

    享元模式是软件设计模式中的一种结构型模式,它的主要目的是减少对象的创建,从而提高系统性能,尤其是在处理大量相似对象时。享元模式通过共享技术来支持大量细粒度对象的复用,将享元对象的状态分为内蕴状态(不可...

    设计模式之享元模式1

    享元模式是一种设计模式,它的主要目的是减少内存中对象的数量,通过共享机制来提高性能,特别是在处理大量具有相同或相似状态的对象时。享元模式的核心思想是区分对象的内部状态(intrinsic state)和外部状态...

    Java设计模式之享元模式.docx

    享元模式是一种面向对象的设计模式,它通过共享技术来减少对象的创建,从而提高系统性能。在Java中,享元模式的一个典型应用是Integer类的缓存机制。当我们创建两个数值相同的Integer对象时,比如Integer i1 = new ...

    C++设计模式之享元模式(Flyweight)

    C++设计模式之享元模式(Flyweight)是一种结构型设计模式,主要用于解决大量相似对象的创建和操作所带来的内存负载问题。该模式的主要设计目标是通过共享对象来减少内存负载,提高系统的性能。 享元模式顾名思义...

    软件设计模式——享元模式设计报告

    享元模式是一种软件设计模式,它的主要目的是为了提高性能,减少对象的创建,尤其是在大量相似对象需要被创建的情况下。在给定的咖啡店案例中,享元模式的应用可以帮助优化内存使用,避免为每杯咖啡的配料表分配独立...

    Python设计模式之享元模式原理与用法实例分析

    本文实例讲述了Python设计模式之享元模式原理与用法。分享给大家供大家参考,具体如下: 享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度的对象. 下面是一个享元模式的demo: #!/usr/bin/env python...

    设计模式的享元模式的例子

    享元模式是软件设计模式中的一种结构型模式,它的主要目的是通过共享大量细粒度对象来减少内存的使用,提高系统性能。在许多场景下,尤其是处理大量相似对象时,享元模式能显著减少内存开销。这个压缩包文件...

    JavaScript设计模式之享元模式实例详解

    本文实例讲述了JavaScript设计模式之享元模式。分享给大家供大家参考,具体如下: 通过两个例子的对比来凸显享元模式的特点:享元模式是一个为了提高性能(空间复杂度)的设计模式,享元模式可以避免大量非常相似类的...

    浅谈JAVA设计模式之享元模式

    "浅谈JAVA设计模式之享元模式" JAVA 设计模式中的享元模式(Flyweight Pattern)是一种结构型设计模式,主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式提供了减少对象数量从而改善应用...

    Java设计模式之享元模式实例详解

    主要介绍了Java设计模式之享元模式,结合实例形式详细分析了享元模式的概念、功能、定义及使用方法,需要的朋友可以参考下

Global site tag (gtag.js) - Google Analytics