`

11-Flyweight: too many objects

阅读更多

The odd thing about flyweight, in the company of the other design patterns, is that it’s a performance hack. It’s generally ideal to simply make an object for every item in your system, but some problems generate a prohibitive number of objects, which may result in excessive slowness or running out of memory.

Flyweight solves this problem by reducing the number of objects. To do this, you externalize some of the data in an object, so that you can pretend that you have more objects than you really do. However, this adds complexity to the interface for using such objects, because you must pass in additional information to method calls in order to tell the method how to find the externalized information.

As a very simple example, consider a DataPoint object that holds an int , a float , and an id that carries the object number. Suppose you need to create a million of these objects, and then manipulate them, like so:

//: flyweight:ManyObjects.java

 

class DataPoint {

  private static int count = 0;

  private int id = count++;

  private int i;

  private float f;

  public int getI() { return i; }

  public void setI(int i) { this.i = i; }

  public float getF() { return f; }

  public void setF(float f) { this.f = f; }

  public String toString() {

    return "id: " + id + ", i = " + i + ", f = " + f;

  }

}

 

public class ManyObjects {

  static final int size = 1000000;

  public static void main(String[] args) {

    DataPoint[] array = new DataPoint[size];

    for(int i = 0; i < array.length; i++)

      array[i] = new DataPoint();

    for(int i = 0; i < array.length; i++) {

      DataPoint dp = array[i];

      dp.setI(dp.getI() + 1);

      dp.setF(47.0f);

    }

    System.out.println(array[size -1]);

  }

} ///:~

 

Depending on your computer, this program may take several seconds to run. More complex objects and more involved operations may cause the overhead to become untenable. To solve the problem the DataPoint can be reduced from a million objects to one object by externalizing the data held in the DataPoint :

//: flyweight:FlyWeightObjects.java

 

class ExternalizedData {

  static final int size = 5000000;

  static int[] id = new int[size];

  static int[] i = new int[size];

  static float[] f = new float[size];

  static {

    for(int i = 0; i < size; i++)

      id[i] = i;

  }

}

 

class FlyPoint {

  private FlyPoint() {}

  public static int getI(int obnum) {

    return ExternalizedData.i[obnum];

  }

  public static void setI(int obnum, int i) {

    ExternalizedData.i[obnum] = i;

  }

  public static float getF(int obnum) {

    return ExternalizedData.f[obnum];

  }

  public static void setF(int obnum, float f) {

    ExternalizedData.f[obnum] = f;

  }

  public static String str(int obnum) {

    return "id: " +

      ExternalizedData.id[obnum] +

      ", i = " +

      ExternalizedData.i[obnum] +

      ", f = " +

      ExternalizedData.f[obnum];

  }

}

 

public class FlyWeightObjects {

  public static void main(String[] args) {

    for(int i = 0; i < ExternalizedData.size; i++) {

      FlyPoint.setI(i, FlyPoint.getI(i) + 1);

      FlyPoint.setF(i, 47.0f);

    }

    System.out.println(

      FlyPoint.str(ExternalizedData.size -1));

  }

} ///:~

 

Since all the data is now in ExternalizedData , each call to a FlyPoint method must include the index into ExternalizedData . For consistency, and to remind the reader of the similarity with the implicit this pointer in method calls, the “this index” is passed in as the first argument.

Naturally, it’s worth repeating admonishments against premature optimization. “First make it work, then make it fast – if you have to.” Also, a profiler is the tool to use for discovering performance bottlenecks, not guesswork.

//这个例子比较直接化。比较好理解,但是,具体的应用还是需要实践的。实际上,在应用中就是对一个“对象池”,可以对这些对象进行重复利用。以下这个例子更加直观。

 

Flyweight模式在XML等数据源中应用
我们上面已经提到,当大量从数据源中读取字符串,其中肯定有重复的,那么我们使用Flyweight模式可以提高效率,以唱片CD为例,在一个XML文件中,存放了多个CD的资料.

每个CD有三个字段:
1.出片日期(year)
2.歌唱者姓名等信息(artist)
3.唱片曲目 (title)

其中,歌唱者姓名有可能重复,也就是说,可能有同一个演唱者的多个不同时期 不同曲目的CD.我们将"歌唱者姓名"作为可共享的ConcreteFlyweight.其他两个字段作为UnsharedConcreteFlyweight.

首先看看数据源XML文件的内容:


<?xml version="1.0"?>
<collection>

<cd>
<title>Another Green World</title>
<year>1978</year>
<artist>Eno, Brian</artist>
</cd>

<cd>
<title>Greatest Hits</title>
<year>1950</year>
<artist>Holiday, Billie</artist>
</cd>

<cd>
<title>Taking Tiger Mountain (by strategy)</title>
<year>1977</year>
<artist>Eno, Brian</artist>
</cd>

.......

</collection>


虽然上面举例CD只有3张,CD可看成是大量重复的小类,因为其中成分只有三个字段,而且有重复的(歌唱者姓名).

CD就是类似上面接口 Flyweight:


public class CD {

  private String title;
  private int year;
  private Artist artist;

  public String getTitle() {  return title; }
  public int getYear() {    return year;  }
  public Artist getArtist() {    return artist;  }

  public void setTitle(String t){    title = t;}
  public void setYear(int y){year = y;}
  public void setArtist(Artist a){artist = a;}

}

将"歌唱者姓名"作为可共享的ConcreteFlyweight:

public class Artist {

  //内部状态
  private String name;

  // note that Artist is immutable.
  String getName(){return name;}

  Artist(String n){
    name = n;
  }

}

再看看Flyweight factory,专门用来制造上面的可共享的ConcreteFlyweight:Artist

public class ArtistFactory {

  Hashtable pool = new Hashtable();

  Artist getArtist(String key){

    Artist result;
    result = (Artist)pool.get(key);
    ////产生新的Artist
    if(result == null) {
      result = new Artist(key);
      pool.put(key,result);
      
    }
    return result;
  }

}

当你有几千张甚至更多CD时,Flyweight模式将节省更多空间,共享的flyweight越多,空间节省也就越大.

该例子内容来自:设计模式之Flyweight(享元) FlyWeight模式

分享到:
评论

相关推荐

    angular-flyweight:使用AngularJS的Flyweight模式的示例实现

    使用Flyweight模式的AngularJS 一个示例,展示了如何使用AngularJS 1.4实现Flyweight模式 本地运行 确保已安装 $ git clone https://github.com/iranreyes/angular-flyweight.git # or clone your own fork $ cd ...

    GoF设计整理(C#实现)在示意图、C#代码的基础上,又增加了设计模式意图、使用场景和重构成本,并增加了PDF书签功能。以后还将持续完善。下载.

    - **Flyweight(享元模式)** - 定义:运用共享技术有效地支持大量细粒度的对象。 - 意图:减少对象数量以节省内存。 - 使用场景:大量相似对象时。 - 重构成本:中。 - **Proxy(代理模式)** - 定义:为其他...

    设计模式(Patterns in Java)

    7. **享元(Flyweight)**: - 描述:运用共享技术来有效地支持大量细粒度的对象。 - 目的:减少内存消耗,提高系统性能。 #### 行为型模式 1. **模板方法(Template Method)**: - 描述:定义一个操作中的...

    java 设计模式(中文)

    12. **Flyweight(享元模式)**: - 目标:运用共享技术有效地支持大量细粒度的对象。 - 实现:通过共享相同部分的状态(内在状态),来减少对象的数量,节省内存空间。 #### C. 行为型模式 13. **Command(命令...

    summary of design patterns

    11. 飞行重量(Flyweight): - 目的:减少内存中对象的数量,共享对象的内部状态,以节省内存。 - 应用场景:处理大量细粒度对象,且大多数对象可以共享时。 12. 代理(Proxy): - 目的:为其他对象提供一种...

    24种设计模式介绍与6大设计原则

    #### 11. **桥梁模式**(Bridge Pattern) - 描述:将抽象部分与它的实现部分分离,使它们都可以独立地变化。 #### 12. **命令模式**(Command Pattern) - 描述:将请求封装为一个对象,从而让你可用不同的请求...

    java设计模式

    11. **桥梁模式(Bridge Pattern)** - 介绍:将抽象部分与实现部分分离,使它们都可以独立地变化。 12. **命令模式(Command Pattern)** - 介绍:将请求封装为对象,这样可以使用不同的请求、队列或者日志请求...

    23种设计模式汇集       

    - **享元模式 (Flyweight)** - 定义:运用共享技术有效地支持大量细粒度的对象。 - 应用场景:减少大量相似对象的内存消耗,如字体字符渲染。 #### C. 行为型模式 - **命令模式 (Command)** - 定义:将一个请求...

    赞助人-Flyweigth:Patrones dediseño

    【标题】:“赞助人-Flyweight:设计模式” 在软件工程中,“Flyweight”(享元)设计模式是一种结构型模式,它旨在有效支持大量细粒度对象的复用,从而减少内存消耗并提高性能。这个模式的名字来源于“轻量级”的...

    10-Flyweight.rar

    2. **Concrete Flyweight(具体享元)类**:实现了Flyweight接口,提供了具体的业务实现。每个具体享元实例都是可共享的,它们共同维护内部状态。 3. **Flyweight Factory(享元工厂)**:负责创建和管理享元对象,...

    flyweight:一个实现flyweight设计模式的C ++ 11库

    MNMLSTC Flyweight是一个小型且易于使用的C ++ 11库,它实现了。 它是仅标头的库。 有关安装和使用MNMLSTC Flyweight的信息(及其限制),请参见其文档。 MNMLSTC Flyweight是根据Apache 2.0许可发布的。 基本范例...

    设计模式学习笔记--Flyweight享元模式.docx

    享元模式的核心是Flyweight类,它是需要被共享的对象,通常包含两个部分:内在状态(Intrinsic State)和外在状态(Extrinsic State)。内在状态是指对象内部不变的部分,可以在多个对象之间共享;外在状态是随环境...

    uu-design-pattern:23种设计模式案例

    |- singleton 单例模式案例 |- structural(结构型模式) |- facade 外观模式案例 |- decorator 装饰器模式案例 |- adapter 适配器模式案例 |- flyweight 享元模式案例 |- composite 组合模式案例

    design-patterns:头先设计模式

    - 享元模式(Flyweight):通过共享技术,有效地支持大量细粒度的对象。 - 装饰器模式(Decorator):动态地给一个对象添加一些额外的职责,增加功能而不影响其他对象。 - 代理模式(Proxy):为其他对象提供一个...

    23种设计模式 C++ PDF

    11. **Interpreter模式**:给出一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语义规则组成的字符串。 - 实例:在实现简单的数学表达式求值时,可以通过解释器模式来...

    design-patterns:学习设计模式

    2. 结构型模式:包括适配器(Adapter)、桥接(Bridge)、组合(Composite)、装饰(Decorator)、外观(Facade)、享元(Flyweight)和代理(Proxy)。它们主要处理对象的组合和结构关系,增强类与对象的灵活性。 ...

    oh-my-design-patterns::artist_palette:记录我在学习设计模式时编写的文章和代码

    装饰模式(Decorator Pattern) Java Kotlin外观模式(Facade Pattern) Java享元模式(Flyweight Pattern) Java代理模式(Proxy Pattern) Java Kotlin行为型(Behavioral)解释器模式(Interpreter Pattern) ...

    java与模式源码-javapatterns:java与模式---源代码

    2. 结构型模式:适配器模式(Adapter)、装饰器模式(Decorator)、桥接模式(Bridge)、组合模式(Composite)、外观模式(Facade)、享元模式(Flyweight)、代理模式(Proxy)。这些模式主要关注类和对象的组合,...

Global site tag (gtag.js) - Google Analytics