您的位置:首页 > 其它

.NET设计模式(13):享元模式(Flyweight Pattern)

2009-02-05 13:07 375 查看

.NET设计模式(13):享元模式(Flyweight Pattern)

享元模式(Flyweight Pattern)

——.NET设计模式系列之十三

Terrylee,2006年3月

摘要:面向对象的思想很好地解决了抽象性的问题,一般也不会出现性能上的问题。但是在某些情况下,对象的数量可能会太多,从而导致了运行时的代价。那么我们如何去避免大量细粒度的对象,同时又不影响客户程序使用面向对象的方式进行操作?

本文试图通过一个简单的字符处理的例子,运用重构的手段,一步步带你走进Flyweight模式,在这个过程中我们一同思考、探索、权衡,通过比较而得出好的实现方式,而不是给你最终的一个完美解决方案。

主要内容:

1. Flyweight模式解说

2..NET中的Flyweight模式

3.Flyweight模式的实现要点

……

概述

面向对象的思想很好地解决了抽象性的问题,一般也不会出现性能上的问题。但是在某些情况下,对象的数量可能会太多,从而导致了运行时的代价。那么我们如何去避免大量细粒度的对象,同时又不影响客户程序使用面向对象的方式进行操作?

意图

运用共享技术有效地支持大量细粒度的对象。[GOF 《设计模式》]

结构图

// "Charactor"

public abstract class Charactor

// "CharactorA"

public class CharactorA : Charactor

// "CharactorB"

public class CharactorB : Charactor

// "CharactorC"

public class CharactorC : Charactor

// "Charactor"

public abstract class Charactor

// "CharactorA"

public class CharactorA : Charactor

// "CharactorB"

public class CharactorB : Charactor

// "CharactorC"

public class CharactorC : Charactor

// "CharactorFactory"

public class CharactorFactory

public class Program

// "Charactor"

public abstract class Charactor

// "CharactorA"

public class CharactorA : Charactor

// "CharactorB"

public class CharactorB : Charactor

// "CharactorC"

public class CharactorC : Charactor

// "CharactorFactory"

public class CharactorFactory

public class Program

// "CharactorFactory"

public class CharactorFactory

public class Program

{

public static void Main(string[] args)

{

string s1 = "abcd";

string s2 = "abcd";

Console.WriteLine(Object.ReferenceEquals(s1,s2));

Console.ReadLine();

}

}

可以看到,输出的结果为True。但是大家要注意的是如果再有一个字符串s3,它的初始值为“ab”,再对它进行操作s3 = s3 + “cd”,这时虽然s1和s3的值相同,但是它们的引用是不同的。关于String的详细情况大家可以参考SDK,这里不再讨论了。

效果及实现要点

1.面向对象很好的解决了抽象性的问题,但是作为一个运行在机器中的程序实体,我们需要考虑对象的代价问题。Flyweight设计模式主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。

2.Flyweight采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实现方面,要注意对象状态的处理。

3.享元模式的优点在于它大幅度地降低内存中对象的数量。但是,它做到这一点所付出的代价也是很高的:享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。另外它将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。

适用性

当以下所有的条件都满足时,可以考虑使用享元模式:

1、 一个系统有大量的对象。

2、 这些对象耗费大量的内存。

3、 这些对象的状态中的大部分都可以外部化。

4、 这些对象可以按照内蕴状态分成很多的组,当把外蕴对象从对象中剔除时,每一个组都可以仅用一个对象代替。

5、 软件系统不依赖于这些对象的身份,换言之,这些对象可以是不可分辨的。

满足以上的这些条件的系统可以使用享元对象。最后,使用享元模式需要维护一个记录了系统已有的所有享元的表,而这需要耗费资源。因此,应当在有足够多的享元实例可供共享时才值得使用享元模式。

总结

Flyweight模式解决的是由于大量的细粒度对象所造成的内存开销的问题,它在实际的开发中并不常用,但是作为底层的提升性能的一种手段却很有效。

参考资料

Erich Gamma等,《设计模式:可复用面向对象软件的基础》,机械工业出版社

Robert C.Martin,《敏捷软件开发:原则、模式与实践》,清华大学出版社

阎宏,《Java与模式》,电子工业出版社

Alan Shalloway James R. Trott,《Design Patterns Explained》,中国电力出版社

MSDN WebCast 《C#面向对象设计模式纵横谈(12):Flyweight享元模式(结构型模式)》
http://www.dofactory.com/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: