动机:采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行代价——主要指内存需求方面的代价。如何在避免大量细粒度对象问题的同 时,让外部客户程序仍然可以透明地使用面向对象的方式来进行操做?
意图:运用共享技术有效地支持大量细粒度的对象。数据库
UML图解:编程
Flyweight模式现实中的应用:设计模式
1.现行的博客、企业、商务网站中其网站的代码本质上是同样的,不同的只是具体的数据和模板而代码核心和数据库倒是共享的;因此现行的作法是将每一个用户的博客或网站整合到一个网站中,共享其相关的代码和数据,这样对于硬盘、内存、CPU、数据库空间等服务器资源均可以达成共享,减小服务器资源的浪费,而对于代码,因为是一份实例,维护和扩展都更加容易;
2.再好比,.NET下字符串string 对象的也是运用了Flyweight模式,string a="享元设计模式";string b="享元设计模式";Object.ReferenceEquals(a,b);返回结果是true;
3.像围棋、五子棋、跳棋等等,它们都有大量的棋子对象,而它们的内部状态(如颜色,大小)都是恒定的; 而外部状态(坐标)倒是变化的,就围棋而论,一盘棋理论上有361个空位能够放棋子,若是用常规的面向对象方式编程,每盘棋可能有两三百个棋子对象产生,一台服务器就很难支持更多的玩家玩围棋游戏了,因此,现行的设计是采用享元设计模式解决这种服务器空间有限问题,采用此设计模式至少棋子对象能够减小到只有两个实例。服务器
示例:以五子棋游戏为例;代码以下ide
namespace Flyweight { /// <summary> /// 抽象棋子类 /// </summary> public abstract class Chess { Color color; public string nickName { get; set; } /// <summary> /// 棋子颜色 /// </summary> public Color Color { get { return color; } } /// <summary> /// 棋子名称 /// </summary> public string NickName { get { return nickName; } } protected Chess(Color c, string nickname) { color = c; nickName = nickname; } /// <summary> /// 在棋盘上画出自身 /// </summary> /// <param name="p"></param> /// <param name="radius"></param> public abstract void Draw(Point p, int radius); } /// <summary> /// 五子棋 /// </summary> public class FiveChess:Chess { public FiveChess(Color c,string name) : base(c, name) { } public override void Draw(Point p, int radius) { //画五子棋代码实现.... } } /// <summary> /// 生产五子棋棋子工厂类 /// </summary> public static class FiveChessFactory { private static Hashtable chessTable = new Hashtable(); public static Chess GetChess(Color key) { if (!chessTable.ContainsKey(key)) { chessTable.Add(key, new FiveChess(key,key.Name+"方")); } return (Chess)chessTable[key]; } } /// <summary> /// 客户程序 /// </summary> public class FiveChessGame { public static void Main() { //红方VS黑方 能够将坐标位置用两个集合来储存,用来判断输赢 FiveChessFactory.GetChess(Color.Red).Draw(new Point(5, 5), 3); FiveChessFactory.GetChess(Color.Black).Draw(new Point(5, 10), 3); FiveChessFactory.GetChess(Color.Red).Draw(new Point(5, 0), 3); FiveChessFactory.GetChess(Color.Black).Draw(new Point(5,15 ), 3); FiveChessFactory.GetChess(Color.Red).Draw(new Point(10,5 ), 3); FiveChessFactory.GetChess(Color.Black).Draw(new Point(20, 5), 3); //这样不管红方和黑方下多少棋子,只有红棋子和黑棋子两个具体实例对象,大大下降了系统的消耗 } } }
Flyweight模式的几个要点:网站
一、面向对象很好滴解决了抽象性的问题,可是做为一个运行在机器中的程序实体,咱们须要考虑对象的代价问题。Flyweight设计模式主要解决面向对象的代价问题,通常不触及面向对象的抽象性问题。
二、Flyweight采用对象共享的作法来下降系统中对象的个数,从而下降细粒度对象给系统带来的内存压力。在具体 实现方面,要注意对象状态的处理
三、对象的数量太大从而致使对象内存开销大——什么样的数量才算大?这须要咱们仔细的根据具体应用状况进行评估,而不能凭空臆断spa