面向對象設計模式之Flyweight享元模式(結構型)

動機:採用純粹對象方案的問題在於大量細粒度的對象會很快充斥在系統中,從而帶來很高的運行代價——主要指內存需求方面的代價。如何在避免大量細粒度對象問題的同 時,讓外部客戶程序仍然可以透明地使用面向對象的方式來進行操做?
意圖:運用共享技術有效地支持大量細粒度的對象。數據庫

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

相關文章
相關標籤/搜索