今天要介紹的是 Object Pool模式,會以工廠的機器為例。假設今天要生產晶片,需要高精密的機器才能去生產,而這台機器又非常昂貴,而且做出機器需要花的時間很長,以老闆的角度來看,資金有限,除非真的需要更多台機器才會去添加購買,並且也要設定能買的最高上限數量,畢竟機器很昂貴,如果買太多會導致資金週轉不靈。
今天如果生產完晶片A,那就會讓機器做閒置的動作,等到有下一個產品需要生產時再拿出來使用,達到重複利用的價值(畢竟機器很貴,買了就是要給他操下去),而如果今天需求大爆發,每一台機器都在被使用,這樣就會需要去等待,直到有機器空閒時才能做生產,接下來我們看例子來說明。
在建立物件比較昂貴,或者對於特定類型能夠建立的物件數目有限制時,管理物件的再利用。
(圖片來源:https://oowisdom.csse.canterbury.ac.nz/images/0/06/Object_pool.PNG)
Machine
簡單定義了機器的名稱以及目前是否閒置(這邊透過 Enum
去表示機器是否閒置)。Factory
可以想成是管理機器的工廠,任何人要使用機器都要到這邊去拿,而裡面有定義好機器最多能擁有的數量,以及一個蒐集Machine
的物件池(_objPool
),會透過這個物件池來存放機器 ( 正常的物件池概念應該是會真的從池裡拿出物件以及放回物件,這邊我用isIdle
的屬性值來代表機器是否閒置,如果閒置則表示機器目前沒有被拿出,非閒置則表示機器已被拿出 )。using System;
using System.Collections.Generic;
using System.Linq;
namespace DAY19_Object_Pool
{
public class Program
{
static void Main(string[] args)
{
Factory factory = new Factory();
factory.GetMachine();
factory.GetMachine();
factory.GetMachine();
factory.GetMachine();
factory.GetMachine();
Factory.ReleaseMachine();
Factory.ReleaseMachine();
factory.GetMachine();
factory.GetMachine();
factory.GetMachine();
Factory.ReleaseMachine();
Factory.ReleaseMachine();
Factory.ReleaseMachine();
factory.GetMachine();
factory.GetMachine();
factory.GetMachine();
Factory.ReleaseMachine();
factory.GetMachine();
factory.GetMachine();
factory.GetMachine();
Console.Read();
}
}
public class Factory
{
// 機器編碼
private static int Number = 1;
// 限制機器最大擁有數量
private static readonly int _poolMaxSize = 3;
// 對象池
private static readonly List<Machine> _objPool = new List<Machine>(_poolMaxSize);
public Machine GetMachine()
{
Machine Machine;
// 判斷對象池數量是否已達上限,如果沒有,則新增機器,如果已達上限,則去取回可用的機器
if (_objPool.Count >= _poolMaxSize && _objPool.Count > 0)
Machine = RetrieveFromPool();
else
Machine = GetNewMachine();
return Machine;
}
private Machine GetNewMachine()
{
// 新增機器
Machine Machine = new Machine() { Name = $"機器{Number++}號", Status = MachineStatus.isNotIdle };
_objPool.Add(Machine);
Console.WriteLine($"新增{Machine.Name}");
return Machine;
}
protected Machine RetrieveFromPool()
{
Machine Machine;
Machine =_objPool.FirstOrDefault(x => x.Status == MachineStatus.isIdle);
if (Machine == null)
{
Console.WriteLine("無空閒的機器,請稍後再試!");
}
else
{
Machine.Status = MachineStatus.isNotIdle;
Console.WriteLine($"使用空閒的機器:{Machine.Name}");
}
return Machine;
}
public static void ReleaseMachine()
{
Random rnd = new Random();
var machine = _objPool.Where(x => x.Status == MachineStatus.isNotIdle).FirstOrDefault();
machine.Status = MachineStatus.isIdle;
Console.WriteLine($"{machine.Name}已釋放,目前可使用!");
}
}
public class Machine
{
public string Name { get; set; }
public MachineStatus Status { get; set; }
}
public enum MachineStatus
{
isIdle,
isNotIdle
}
}
透過 Object Pool模式,當我們在建立昂貴物件的時候 (假設一個物件需要透過大量的資料庫連線以及計算,甚至要花很長的等待時間),就可以使用物件池的概念,將這些昂貴的物件放置在一個物件池,如果需要就拿出來使用,用完就放回去,減少每次都要重複花費高成本在建立昂貴物件。