C#設計模式系列:享元模式(Flyweight)

libingql發表於2014-03-31

  當頻繁地從資料來源讀取資料時,讀出的內容存在重複,那麼需要使用享元模式(Flyweight)來提高記憶體效率,Flyweight模式將節省更多空間,共享的Flyweight越多,空間節省越大。

1、享元模式簡介

1.1>、定義

  享元模式(Flyweight)的存在是為了避免大量擁有相同內容的小類的開銷(如記憶體開銷),使大家共享一個類。

1.2>、使用頻率

   

2、享元模式結構

2.1>、結構圖

 

2.2>、參與者

  享元模式參與者:

  ◊ Flyweight:宣告一個介面,通過這個介面flyweight可以直接接收並作用於外部狀態。

  ◊ ConcreteFlyweight:實現Flyweight介面,併為內部狀態增加儲存空間。ConcreteFlyweight物件必須是可以共享的,它所儲存的狀態必須是內部的,即它必須獨立於ConcreteFlyweight物件的場景。

  ◊ UnsharedConcreteFlyweight:並非所有的Flyweight子類都需要被共享。Flyweight介面使共享成為可能,但它不強制共享。在Flyweight物件結構的某些層次,UnsharedConcreteFlyweight物件通常將ConcreteFlyweight物件作為子節點。

  ◊ FlyweightFactory

    ° 建立和管理flyweight物件。

    ° 確保flyweight物件被合理共享。當Client請求一個flyweight物件時,FlyweightFactory需要可以進行分配,若flyweight物件不存在時,則先建立一個。

  ◊ Client:維持一個對Flyweight的引用

  在享元模式中,Client呼叫Flyweight下的ConcreteFlyweight,如果ConcreteFlyweight存在則呼叫成功;否則就呼叫FlyweightFactory生產所需要的繼承Flyweight介面的ConcreteFlyweight,以供呼叫。

3、享元模式結構實現

  Flyweight.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.FlyweightPattern.Structural
{
    public abstract class Flyweight
    {
        public abstract void Operation(int extrinsicstate);
    }
}

  ConcreteFlyweight.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.FlyweightPattern.Structural
{
    public class ConcreteFlyweight : Flyweight
    {
        public override void Operation(int extrinsicstate)
        {
            Console.WriteLine("ConcreteFlyweight: " + extrinsicstate);
        }
    }
}

  UnsharedConcreteFlyweight.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.FlyweightPattern.Structural
{
    public class UnsharedConcreteFlyweight : Flyweight
    {
        public override void Operation(int extrinsicstate)
        {
            Console.WriteLine("UnsharedConcreteFlyweight: " + extrinsicstate);
        }
    }
}

  FlyweightFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Collections;

namespace DesignPatterns.FlyweightPattern.Structural
{
    public class FlyweightFactory
    {
        private Hashtable flyweights = new Hashtable();

        public FlyweightFactory()
        {
            flyweights.Add("X", new ConcreteFlyweight());
            flyweights.Add("Y", new ConcreteFlyweight());
            flyweights.Add("Z", new ConcreteFlyweight());
        }

        public Flyweight GetFlyweight(string key)
        {
            return ((Flyweight)flyweights[key]);
        }
    }
}

  Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DesignPatterns.FlyweightPattern.Structural;

namespace DesignPatterns.FlyweightPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            // Arbitrary extrinsic state
            int extrinsicstate = 22;
            FlyweightFactory factory = new FlyweightFactory();

            // Work with different flyweight instances
            Flyweight fx = factory.GetFlyweight("X");
            fx.Operation(--extrinsicstate);

            Flyweight fy = factory.GetFlyweight("Y");
            fy.Operation(--extrinsicstate);

            Flyweight fz = factory.GetFlyweight("Z");
            fz.Operation(--extrinsicstate);

            UnsharedConcreteFlyweight fu = new UnsharedConcreteFlyweight();
            fu.Operation(--extrinsicstate);
        }
    }
}

  執行輸出:

ConcreteFlyweight: 21
ConcreteFlyweight: 20
ConcreteFlyweight: 19
UnsharedConcreteFlyweight: 18
請按任意鍵繼續. . .

4、享元模式應用分析

  享元模式適用情形:

  ◊ 一個應用程式使用了大量的物件

  ◊ 完全由於使用大量的物件,造成很大的儲存開銷

  ◊ 物件的大多數狀態都可變為外部狀態

  ◊ 如果刪除物件的外部狀態,那麼可以用相對較少的共享物件取代很多組物件

  ◊ 應用程式不依賴物件標識

  享元模式特點:

  ◊ 享元模式的核心是把大量共享的物件收集在一起使用簡單工廠模式進行管理,避免由於大量的小物件導致系統記憶體過度消耗。

  ◊ 享元當重複物件較多時有很好的空間複雜度,但在查詢搜尋上消耗了時間複雜度。

相關文章