结构型--享元模式(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. 享元模式,其实类似一个容器,将需要重复全多次被创建的对像, 只创建一次并放到这个容器中, 如果有需要,则从这个容器中查找并取出.