原文
概述:
面向对象的思想很好地解决了抽象性的问题,一般也不会出现性能上的问题。但是在某些情况下,对象的数量可能会太多,从而导致了运行时的代价。那么我们如何去避免大量细粒度的对象,同时又不影响客户程序使用面向对象的方式进行操作?享元模式j就可以让我们更好的复用我们内存中已存在的对象,降低系统创建对象实例的性能消耗
运用共享技术有效地支持大量细粒度的对象。[GOF 《设计模式》]
结构图:
举例:
为了方便说清享元模式的核心,我就把其它不相关的代码给去了,就留下核心的代码进行说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | //字母基类 abstract class English { public abstract void Method(); } //字母A class A : English { public override void Method() { Console.WriteLine( "我是A" ); } } //字母B class B : English { public override void Method() { Console.WriteLine( "我是B" ); } } /// <summary> /// 享元工厂 /// </summary> class Factory { Dictionary< string , English> list = new Dictionary< string , English>(); public Factory() { list.Add( "A" , new A()); list.Add( "B" , new B()); } //获取实例 public English Get( string str) { if (list[str] == null ) { list[str] = (English)Activator.CreateInstance(Type.GetType( "享元模式." + str)); } return list[str]; } } //客户端调用 class Program { static void Main( string [] args) { Factory f = new Factory(); English e = f.Get( "A" ); e.Method(); Console.ReadLine(); } } |
通过上面的代码,我们可以看到我们调用对象的时候不在是直接new 一个对象了。而是通过调用享元工厂的方法来复用我们内存中已经存在的对象。这样避免了new对象中产生的不必要的开销!
单例模式跟享元模式的区别
享元模式是为了节约内存空间,提升程序性能(避免大量的new操作);
而单例模式则主要是出于共享状态的目的;
设计模式不用拘泥于具体代码, 代码实现可能有n多种方式, 而单例可以看做是享元的实现方式中的一种, 但是他比享元更加严格的控制了对象的唯一性。
适用场景:
1、 一个系统有大量的对象。
2、 这些对象耗费大量的内存。
3、 这些对象的状态中的大部分都可以外部化。
4、 这些对象可以按照内蕴状态分成很多的组,当把外蕴对象从对象中剔除时,每一个组都可以仅用一个对象代替。
5、 软件系统不依赖于这些对象的身份,换言之,这些对象可以是不可分辨的。
满足以上的这些条件的系统可以使用享元对象。最后,使用享元模式需要维护一个记录了系统已有的所有享元的表,而这需要耗费资源。因此,应当在有足够多的享元实例可供共享时才值得使用享元模式。
: