享元模式 Flyweight
Intro
享元是指一個可復用的對象,通過復用這個享元來減少應用中的內存分配。
享元模式是為了減少內存占用,盡可能復用已有對象的設計模式,一般來說會把這個可復用的對象放到一個外部的數據結構中,當需要使用到的時候傳給享元。
享元模式的意圖是復用對象,節省內存,前提是享元對象是不可變對象。
具體來講,當一個系統中存在大量重復對象的時候,我們就可以利用享元模式,將對象設計成享元,在內存中只保留一份實例,供多處代碼引用,這樣可以減少內存中對象的數量,以起到節省內存的目的。
實際上,不僅僅相同對象可以設計成享元,對于相似對象,我們也可以將這些對象中相同的部分(字段),提取出來設計成享元,讓這些大量相似對象引用這些享元。
Sample
public abstract class Flyweight
{
public abstract void Operation(int extrinsicstate);
}
public class ConcreteFlyweight : Flyweight
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("operation in ConcreteFlyweight");
}
}
public class UnsharedFlyweight : Flyweight
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("operation in UnsharedFlyweight");
}
}
public class FlyWeightFactory
{
private readonly ConcurrentDictionary<string, Flyweight> _flyweights = new ConcurrentDictionary<string, Flyweight>();
public Flyweight GetFlyweight(string name) => _flyweights.GetOrAdd(name, n => new ConcreteFlyweight());
}
public class Program
{
public static void Main(string[] args)
{
var counter = 20;
var factory = new FlyWeightFactory();
factory.GetFlyweight("X").Operation(counter--);
factory.GetFlyweight("Y").Operation(counter--);
factory.GetFlyweight("X").Operation(counter--);
new UnsharedFlyweight().Operation(counter--);
factory.GetFlyweight("X").Operation(counter--);
Console.WriteLine(counter);
Console.ReadLine();
}
}
More
享元模式的代碼實現非常簡單,主要是通過工廠模式,在工廠類中,通過一個 Dictionary 或數組等 來緩存已經創建好的享元對象,以達到復用的目的,可以參考上面的示例。
來看一道經典的 C# 面試題目:
var a = "Hello World";
var b = "Hello World";
Console.WriteLine(ReferenceEquals(a, b));
想一下輸出結果是什么,不確定的話可以試一下哈
CLR 中 string 是一個特殊的類型,string 有一個字符串池(Intern ) 的實現就屬于是享元模式的體現,這也是上面的輸出結果的原因,相同的字符串變量值指向了同一塊內存地址
Reference
|