Java语言设计模式之享元模式(Flyweight)
2017-08-29 15:15
246 查看
Flyweidht 模式可能让人感到奇怪的一点是: 它(在其它模式的辅助下)是改善性能(performance hack)的一种方法。 通常来说比较好的做法就是简单的把系统里所有东西都弄成对象,但是有时候这样做会使得产生的对象数量非常巨大,这可能会导致系统过于缓慢或者内存耗尽。
Flyweight 模式通过减少对象数量来解决这个问题。为了达到这个目的,需要外部化(externalize)原本属于对象一些数据,这样使得看起来对象的数量要比实际的多。但是,这同时也增加了应用这些对象时接口的复杂度,因为你必须传入额外的信息用以告诉调用方法如何找到那些外部化的信息。
作为一个非常简单的例子,考虑一个 DataPoint 对象,它包含一个 int 和 float类型的数据成员,还有一个 id 数据成员用来表示对象编号。假设你需要创建五百万个这样的对象,然后对它们进行操作,像下面这样:
ManyObjects .java
上面这个程序运行下来可能需要几秒钟,这取决于你的机器。更复杂的对象和更
多的操作可能会使额外开销难以维持。为了解决这个问题,我们通过外部化原本属于DataPoint 数据成员的方法,使对象个数从一百万个减少到一个。
FlyWeightObjects.java
这么一来,因为所有数据都存放在 ExternalizedData 里,所以每个对 FlyPoint方法的调用都必须包含对 ExternalizedData 的索引。出于一致性的考虑,而且也是为了提醒读者注意(FlyPoint)各个方法的隐含(implicit)this 指针的相似性,“this 索引”是作为第一个参数传入的。
自然,这里又要对过早优化(premature optimization)提出警告。“先让程序能够运行起来,如果确有这个必要的话,再想办法提高速度。”再说一次,用profiler 工具来检测性能瓶颈,而不要靠猜测。
Flyweight 模式通过减少对象数量来解决这个问题。为了达到这个目的,需要外部化(externalize)原本属于对象一些数据,这样使得看起来对象的数量要比实际的多。但是,这同时也增加了应用这些对象时接口的复杂度,因为你必须传入额外的信息用以告诉调用方法如何找到那些外部化的信息。
作为一个非常简单的例子,考虑一个 DataPoint 对象,它包含一个 int 和 float类型的数据成员,还有一个 id 数据成员用来表示对象编号。假设你需要创建五百万个这样的对象,然后对它们进行操作,像下面这样:
ManyObjects .java
package com.enfo.wd.factory; 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; } @Override public String toString() { return "[id=" + id + ", i=" + i + ", f=" + f + "]"; } } public class ManyObjects { static final int size=5000000; public static void main(String[] args){ DataPoint[] arrays=new DataPoint[size]; for(int i=0;i<arrays.length;i++) arrays[i]=new DataPoint(); for(int i=0;i<arrays.length;i++){ DataPoint dp=arrays[i]; dp.setI(dp.getI()+1); dp.setF(47.0f); } System.out.println(arrays[size-1]); } }
上面这个程序运行下来可能需要几秒钟,这取决于你的机器。更复杂的对象和更
多的操作可能会使额外开销难以维持。为了解决这个问题,我们通过外部化原本属于DataPoint 数据成员的方法,使对象个数从一百万个减少到一个。
FlyWeightObjects.java
package com.enfo.wd.factory; class ExternlizedData{ 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 ExternlizedData.i[obnum]; } public static void setI(int obnum,int i){ ExternlizedData.i[obnum]=i; } public static float getF(int obnum) { return ExternlizedData.f[obnum]; } public static void setF(int obnum,float f) { ExternlizedData.f[obnum]=f; } public static String str(int obnum){ return "id:"+ExternlizedData.id[obnum]+ ",i="+ExternlizedData.i[obnum]+ ",f="+ExternlizedData.f[obnum]; } } public class FlyWeightObjects { public static void main(String[] args) { for(int i=0;i<ExternlizedData.size;i++){ FlyPoint.setI(i, FlyPoint.getI(i)+1); FlyPoint.setF(i, 47.0f); } System.out.println(FlyPoint.str(ExternlizedData.size- a767 1)); } }
这么一来,因为所有数据都存放在 ExternalizedData 里,所以每个对 FlyPoint方法的调用都必须包含对 ExternalizedData 的索引。出于一致性的考虑,而且也是为了提醒读者注意(FlyPoint)各个方法的隐含(implicit)this 指针的相似性,“this 索引”是作为第一个参数传入的。
自然,这里又要对过早优化(premature optimization)提出警告。“先让程序能够运行起来,如果确有这个必要的话,再想办法提高速度。”再说一次,用profiler 工具来检测性能瓶颈,而不要靠猜测。
相关文章推荐
- Java设计模式----享元模式(FlyWeight)
- Java设计模式二十二:享元模式(Flyweight)
- Java设计模式——享元模式(Flyweight)
- 浅谈Java设计模式(十二)享元模式(Flyweight)
- Java设计模式----享元模式(FlyWeight)
- Java设计模式二十二:享元模式(Flyweight)
- java设计模式12——享元模式(Flyweight)
- JAVA设计模式之享元模式Flyweight
- JAVA设计模式(08):结构型-享元模式(Flyweight)
- Java设计模式之共享模式/享元模式(Flyweight模式)介绍
- Java开发中的23种设计模式详解----享元模式(Flyweight)
- Java设计模式-----FlyWeight享元模式
- java23种设计模式--享元模式(flyweight)
- java设计模式(十一)——享元模式(Flyweight)
- Java设计模式(5)共享模式/享元模式(Flyweight模式)
- JAVA设计模式(12) —<结构型>享元模式(Flyweight)
- 详解Java设计模式编程中的Flyweight享元模式的开发结构
- Java开发中的23种设计模式之十二:享元模式(Flyweight)
- Java设计模式——享元模式(Flyweight)
- Java设计模式之结构型模式-享元模式(Flyweight)