结构型--享元模式(Flyweight Pattern)

1、意图

享元模式:运用共享技术有效地支持大量细粒度的对象

2、核心思想

      享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外蕴状态。

     内蕴状态存储在享元内部,不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态,它们是相互独立的。

      将可以共享的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出去。

      客户端不可以直接创建被共享的对象,而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。

3、优缺点分析

GOOD:

(1)运用共享技术有效地支持大量细粒度的对象(对于C++来说就是共用一个内存块啦,对象指针指向同一个地方)。

(2)如果一个应用程序使用了大量的对象,而这些对象造成了很大的存储开销就应该考虑使用。

(3)还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用较少的共享对象取代多组对象,此时可以考虑使用享元。

4、实例

我们不妨假设QQ是在服务器端将每次的对话都抽象出来形成了一个类。于是代码如下:

class People
{
    private string name;
    private int age;
    public string Name
    {
        get
        {
            return name;
        }
    }
    public int Age
    {
        get
        {
            return age;
        }
        set
        {
            age = value;
        }
    }
    public People(string name, int age)
    {
        this.name = name;
        this.age = age;
    }
}

class Chat
{
    private People boy;
    private People girl;
    private string chatContent;

    public Chat(People p1, People p2)
    {
        this.boy = p1;
        this.girl = p2;
    }
    public string ChatContent
    {
        get
        {
            return chatContent;
        }
        set
        {
            chatContent = value;
        }
    }
    public People Boy
    {
        get
        {
            return boy;
        }
    }
    public People Girl
    {
        get
        {
            return girl;
        }
    }
}

若每次二者聊天时均将Chat实例化为一个对象,如下:

class Program
{
    static void Main(string[] args)
    {
        People boy=new People("PrettyBoy",20);
        People girl=new People("BeautifulGirl",18);
        Chat chat = new Chat(boy, girl);
        chat.ChatContent = "I love you";
        ChatServer.Send(chat);
    }
}

若如此,服务器就需要每次都去初始化一个对象,而当chatServer将此次聊天的记录发送给客户机之后,这个对象便成了垃圾对象。这样,每小时几百万的聊天次数,便有了几百万的对象垃圾。垃圾回收器GC便需要不停地去工作,回收对象。

这就对效率产生了极大的影响。于是,我们想办法,使用享元模式来解决这个问题。

两者聊天,他们的聊天方是不变的,因此,我们可以在服务器端去维护一个这样的Chat对象集合,如果该聊天对象已经存在,那么我们便重复去利用这个聊天对象。这样既减少了内存垃圾,又节省了创建对象的时间。

代码如下:

class FlyweightFactory
{
    private IDictionary<string, Chat> cache = new Dictionary<string, Chat>();

    private void Add(Chat c)
    {
        cache.Add(c.Boy.Name + "_" + c.Girl.Name, c);
    }

    public Chat GetChat(People boy , People girl)
    {
        if (!cache.ContainsKey(boy.Name + "_" + girl.Name))
        {
            cache.Add(boy.Name + "_" + girl.Name, new Chat(boy, girl));
        }
        return cache[boy.Name + "_" + girl.Name];
    }
}

于是,从客户端访问该FlyweightFactory即可。

这样,便有效控制了对象的数量。

参考:http://www.cnblogs.com/kym/archive/2009/03/29/1424255.html

          http://www.cnblogs.com/aspnet2008/archive/2009/02/12/1387230.html

          http://www.cnblogs.com/steven_oyj/archive/2010/06/25/1765358.html

  

刚看到以为园友对该模式的总结,挺不错的。
1. 享元模式实际是单件模式的一个增强.
2. 享元模式,其实类似一个容器,将需要重复全多次被创建的对像, 只创建一次并放到这个容器中, 如果有需要,则从这个容器中查找并取出.

posted @ 2011-02-13 10:36  clound  阅读(361)  评论(0编辑  收藏  举报