`
Dapple
  • 浏览: 101066 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

亨元模式(Flyweight pattern)

阅读更多
翻译为亨元模式,或直译为轻量级模式。所谓亨元,就是被其它对象共享使用的
对象。通过这种方式,系统减少了内存的占用。比如一个系统有一个成百上千、
成千上万的小对象,这些小对象可能拥有着共同的信息,那么这些共同的信息就
没有必要也重复成千上万次。把这些共同信息抽取出来,形成一个对象,即是亨
元。这些成千上万的其它对象只需要引用这个亨元即可。

举个例子,在棋类程序中,有时候我们会把一个棋子当成为一个对象。这个对象
包含着位置信息、字体信息、颜色信息、样式信息等。如下所示,

class 棋子{
  public 名字(车、马、炮等)
  public 位置信息
  public 字体信息
  public 颜色信息
  public 样式信息
}


如果我们每次new一个这样的对象,它所占用的内存是这些信息所占内存的和。
new 10个这样的对象就需要10倍的内存占用。实际上,在象棋中,除了象棋棋子
的名字不同、位置不同外,其它的字体信息、样式信息一般都是一样的。比如红
方的棋子是红色、隶书、字体有阴影效果,黑方的棋子是黑色、隶书、有阴影效
果。

这些字体信息、颜色信息、样式信息都可以做成亨元。拿颜色信息来说,如果不
使用亨元,则每一个棋子都要分别创建一个颜色对象,10个棋子就创建10个颜色
对象,而这10个颜色对象很可能是一样的,比如都是红色。这样就太浪费内存了。
使用亨元,则可以避免这种重复创建相同对象的问题。

我们只需要创建一个红色信息的对象,而让所有红色棋子都引用这个红色对象。
同理,让所有黑色棋子都引用黑色对象。这样就减少了内存使用。

比如,我们在new 一个红色棋子对象时,要先去一个颜色信息池中区查找是否已
经有这么一个红色对象,有则,直接引用它,没有则先创建它再引用它。所谓颜
色信息池,一般都用Map来实现。比如,

Map h = new HashMap();
if(h.get("red")!=null){
    h.pub("red",new Color对象);
}else{
    取出这个Color对象(我们叫它objectC)。
}


然后你在另一个地方把这个objectC赋给棋子对象,比如用这种方式:
棋子对象.颜色信息=objectC;

实际上,针对象棋这个例子也没有必要用一个pool来保存Color对象,也没有必要
判断这个对象是不是在pool中存在,也没必要在判断完是否存在后再进行是否生
成一个新对象的工作。因为象棋中无非两种对象,红和黑,这是确定的。所以我
们完全可以把这两个对象提前生成出来,放到一个地方保存着,别人都对它们进
行引用即可,可以这样做,

class 棋子{
    private static Color redColor = new Color("red");
    private static Color blackColor = new Color("black");
...
...      
}


这好像有点单态模式的感觉。实际上,一个class会共享很多实例而不像单态那样
只允许共享一个实例,也不像象棋这样只有红、黑两种颜色对象。假如一个应用
中,class共享的颜色对象可能除了红、黑,还有其它上百种颜色,而且颜色种类
的增减,依赖于用户的操作,那么用一个pool把它们存放起来就比较好。

一般亨元的获取都是通过一个工厂类来实现,例子如下:

class A{
    private B b;
    private C c;
    private Flyweight f;
    public A(B b,C c,Flyweight f){
        this.b = b;
        this.c = c;
        this.f = f;
    }
}

class Factory{
    private static Factory f = new Factory();
    private static Map m = new HashMap();
    private Factory(){};
    public Factory getInstance(){return f;}
    public void getFlyweight(Object key){
        Flyweight fly;
        if(m.get(key)==null){
             fly = new Flyweight(key);
             f.put(key,fly);
        }else{
             fly = (Flyweight)f.get(key);
        }
        return fly;
     }
}

class Client{
    public static void main(String args[]){
        B b = new B();
        C c = new C();
        Flyweight f = Factory.getInstance().getFlyweight(key);
        A a = new A(b,c,f);
    }
}


下面3个类的具体内容不重要,略
class B
class C
class Flyweight

当用户new一个A的实例,A中的Flyweight对象只是指向共享对象的一个引用。在
这个例子中,使用HashMap来保存共享对象,随着程序的运行,HashMap存的对象
会越来越多,HashMap自己会变的越来越大。有的时候,因为用户的操作也可能会
使对象被杀掉(比如棋子被吃掉),以至于有的亨元没有被任何对象引用,这个
时候,如果本身已经有点臃肿的HashMap能瘦身,自动释放亨元,对系统性能的提
升也非常有好处。比较简单的一个办法就是用WeakHashMap代替HashMap.

Flyweight模式是一种Cache技术,站在更高的层面看,它是一种资源使用技术。
这种技术更多的见于对性能要求比较高的底层开发领域。Java语言中的某县内置
对象可能就是用Flyweight模式实现的。比如最常用的String对象就可能是如此,
可以做一个简单测试,如下,
public class Test {
public static void main(String[] args) {
    String a1 = "aaa"
    String b1 = "bbb";
    String a2 = "aaa";
    String b2 = "bbb"; 
    System.out.println(a1 == a1);
    System.out.println(b1 == b2);                                     
    String c = a + b;
    System.out.println(c == "aaabbb");
    String flyweight = (a + b).intern();//这里用到了亨元模式. 返回"aaabbb"的一个引用。
    System.out.println(flyweight == "aaabbb"); 
  }
}
程序分别返回 true,true,false,true.  (==用来测试两者是不是引用同一个实例).

String在java中的应用甚为频繁,所以使用Flyweight模式以提高性能理所当然,
但事实上String很多地方并未使用该模式,比如

String a =new String("aaa");
String b = new String("bbb");
System.out.println(a == b);


程序打印出false.

或许这是Java为开发者故意提供的一个让同一个字符串有多个实例的选择。

最后要注意的一点是,这些共享的对象有可能在途中被改变。你要根据不同的应
用来决定是不是允许共享对象改变,如果不允许就把它们设计成不可变对象
(immutable)。如果允许变,则要考虑是不是创建个新的亨元同时保留老亨元,或
者通知那些使用亨元的对象亨元已经改变了。根据你的具体情况具体分析具体设
计。
1
2
分享到:
评论
1 楼 lixia0417 2010-08-07  
不错,楼主解释得挺详细的,我认为可能数据库连接池就是用的类似方法实现的;

相关推荐

    享元模式 Flyweight Pattern

    享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。

    设计模式(C#)之享元模式(Flyweight Pattern)

    设计模式(C#)之享元模式(Flyweight Pattern),运用共享技术有效地支持大量细粒度的对象。

    结构型模式之共享元模式(Flyweight)

    6共享元模式(Flyweight) 用意:以共享的方式高效地支持大量的细粒度对象

    C#设计模式之Flyweight

    设计模式 Flyweight

    享元模式flyweight

    NULL 博文链接:https://hnzhoujunmei.iteye.com/blog/1033359

    C#版 24种设计模式

    适配器模式(Adapter Pattern) 提供者模式(Provider Pattern) 外观模式(Facade Pattern) 享元模式(Flyweight Pattern) 原型模式(Prototype Pattern) 责任链模式(Chain of Responsibility Pattern) 中介者模式...

    php设计模式 FlyWeight (享元模式)

    享元模式英文称为“Flyweight Pattern”,我非常感谢将Flyweight Pattern翻译成享元模式的那位强人,因为这个词将这个模式使用的方式明白得表示了出来;如果翻译成为羽量级模式或者蝇量级模式等等,虽然可以含蓄的...

    用Java实现23种设计模式

    享元模式(Flyweight Pattern) 代理模式(Proxy Pattern) 3. 行为型模式 责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式...

    C#设计模式_设计模式_C#_

    享元模式(Flyweight Pattern) 12. 代理模式(Proxy Pattern) 行为型: 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 16. 观察者模式(Observer Pattern) 17. ...

    C#设计模式(23种设计模式)

    享元模式(Flyweight Pattern) 12. 代理模式(Proxy Pattern) 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 行为型: 16. 观察者模式(Observer Pattern...

    Java设计模式,并加上个人理解

    1. 设计模式 1.1 含义 1.2 作用 1.3 设计原则 1.4 分类 2. 简单工厂模式 (SimpleFactoryPattern) ...15. 享元模式 (Flyweight Pattern) 16. 桥接模式 (Bridge Pattern) 17. 观察者模式 (Observer Pattern)

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

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

    设计模式PPT

     享元模式(Flyweight Pattern)  代理模式(Proxy Pattern) 行为型模式用来对类或对象怎样交互和怎样分配职责进行描述,主要包含以下11种设计模式:  责任链模式(Chain of Responsibility Pattern)  ...

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

    主要为大家详细介绍了C++设计模式之享元模式Flyweight,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    C#面向对象设计模式纵横谈\12 结构型模式Flyweight享元模式.zip

    在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要... 这是第12节:结构型模式Flyweight享元模式

    设计模式代码——c#

    11. 享元模式(Flyweight Pattern) 12. 代理模式(Proxy Pattern) 行为型 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 16. 观察者模式(Observer Pattern...

    33种JAVA设计模式DEMO

    享元模式(Flyweight Pattern) 代理模式(Proxy Pattern) 3 行为型模式 这些设计模式特别关注对象之间的通信。 责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式...

    23种设计模式 (创建型,结构型,行为型)

    享元模式(Flyweight Pattern) 12. 代理模式(Proxy Pattern) 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 行为型: 16. 观察者模式(Observer Pattern...

    36种最新设计模式整理

    Design Pattern: Flyweight 模式 46 Design Pattern: Proxy 模式(一) 48 Design Pattern: Proxy 模式(二) 49 Design Pattern: Chain of Responsibility 模式 53 Design Pattern: Command 模式 59 Design Pattern...

    软件模式之Flyweight模式.docx

    软件模式之Flyweight模式.docx

Global site tag (gtag.js) - Google Analytics