设计模式12——结构型模式之享元模式

定义:享元模式(Flyweight Pattern),运用共享技术有效地支持大量细粒度的对象。

类型:结构型模式。

适用情况:

  1. 一个应用程序有大量的对象。
  2. 对象的大多数状态都是外部的。
  3. 如果删除对象的外部状态,可以和相对较少的共享对象取代很多组对象。
  4. 应用程序不依赖对象的标识,即应用程序依赖于对象的抽象接口。

概述:

        Flyweight,原意为“轻量级选手”的意思。翻译者将它意为享元模式,是意译,力求能够直观地表现出此模式的目的。享,共享之意。元,基本单元的意思。享元,也就是共享基本单元,也即GoF所言的运用共享技术有效地支持大量细粒度的对象。

        享元模式的重点在于将对象的“内部状态”和“外部状态”抽象出来,内部状态存储在享元对象中,而外部状态在外部存储。这个才是享元模式的关键,网上很多文章根本没有讲透这一点。

         下面举一个示例。有一棋盘上的围棋正好是大量细粒度的对象。我们将材质、形状、制作工艺抽象为内部状态, 而围棋在棋盘上的位置是标识每一棋子的标记,故棋子的位置抽象为外部状态。而棋子只有白黑两种颜色,如果存储在外部状态里,会存两种颜色很多次。故这里,白棋、黑棋作为两个对象存在。

类图

设计模式12——结构型模式之享元模式

参与者:

  1. Client,调用ChessBoard得到具体的棋子对象。
  2. Chessboard,管理棋子的生成以及存储棋子的外部状态,即每个棋子的具体位置。
  1. Weiqi,围棋抽象类,即享元对象,抽象出一些内部状态来。
  1. WhiteWeiqiBlackWeiqi,两个派生出的不同颜色的围棋,实现颜色接口。

示例代码:

// Flyweight类

[csharp] view plaincopy设计模式12——结构型模式之享元模式设计模式12——结构型模式之享元模式
  1. public abstract class Weiqi  
  2. {  
  3.     // 内部状态  
  4.     // ...............  
  5.     // private int nSize;  
  6.   
  7.     public abstract Color GetColor();  
  8.   
  9. }  

// 具体的Flyweight类

[csharp] view plaincopy设计模式12——结构型模式之享元模式设计模式12——结构型模式之享元模式
  1. public class WhiteWeiqi : Weiqi    {  
  2.         public override Color GetColor()  
  3.         {  
  4.             Console.WriteLine("White");  
  5.             return Color.White;  
  6.         }  
  7.     }  
  8.   
  9.     public class BlackWeiqi : Weiqi  
  10.     {  
  11.         public override Color GetColor()  
  12.         {  
  13.             Console.WriteLine("Black");  
  14.             return Color.Black;  
  15.         }  
  16.     }  

// FlyweightFactory类

[csharp] view plaincopy设计模式12——结构型模式之享元模式设计模式12——结构型模式之享元模式
  1. public class Blessboard    {  
  2.        private List<Point> listWhite = new List<Point>();  
  3.        private List<Point> listBlack = new List<Point>();  
  4.        private WhiteWeiqi wWeiqi;  
  5.        private BlackWeiqi bWeiqi;  
  6.   
  7.        public Blessboard()  
  8.        {  
  9.            wWeiqi = new WhiteWeiqi();  
  10.            bWeiqi = new BlackWeiqi();  
  11.        }  
  12.   
  13.        public Weiqi Produce(bool bWthite, Point pt)  
  14.        {  
  15.            if (bWthite)  
  16.            {  
  17.                listWhite.Add(pt);  
  18.   
  19.                return bWeiqi;  
  20.            }  
  21.            else  
  22.            {  
  23.                listBlack.Add(pt);  
  24.   
  25.                return bWeiqi;  
  26.            }  
  27.        }  
  28.   
  29.        public Weiqi GetProduce(Point pt)  
  30.        {  
  31.            foreach (Point p in listWhite)  
  32.            {  
  33.                if (p.Equals(pt))  
  34.                {  
  35.                    return wWeiqi;  
  36.                }  
  37.            }  
  38.   
  39.            foreach (Point p in listBlack)  
  40.            {  
  41.                if (p.Equals(pt))  
  42.                {  
  43.                    return bWeiqi;  
  44.                }  
  45.            }  
  46.   
  47.            return null;  
  48.        }  
  49.    }  

// Client类

[csharp] view plaincopy设计模式12——结构型模式之享元模式设计模式12——结构型模式之享元模式
  1. class Program    {  
  2.         static void Main(string[] args)  
  3.         {  
  4.             Blessboard bloard = new Blessboard();  
  5.   
  6.             // 生成棋子  
  7.             bloard.Produce(truenew Point(1, 3));  
  8.             bloard.Produce(falsenew Point(2, 3));  
  9.             bloard.Produce(truenew Point(1, 4));  
  10.             bloard.Produce(falsenew Point(2, 4));  
  11.   
  12.             // 查询棋子黑白  
  13.             Weiqi weiqi = bloard.GetProduce(new Point(2, 4));  
  14.             Color color = weiqi.GetColor();  
  15.   
  16.             weiqi = bloard.GetProduce(new Point(1, 4));  
  17.             color = weiqi.GetColor();  
  18.         }  
  19.     }  

 

注意:如果是C++,抽象类一定要注意析构函数一定要是虚函数。

优缺点:

  1. 优点,减少内存的使用。
  1. 缺点,加大了结构的复杂度,需要单独管理外部状态。

参考资料:

  1. 《设计模式——可复用面向对象软件基础》
  1. 《大话设计模式》
  1. 《Head First设计模式》

设计模式12——结构型模式之享元模式

上一篇:linux 静态库使用经验


下一篇:Sys未定义处理方法