Fork me on GitHub
Object Pool

设计模式之美:Object Pool(对象池)

 

索引

意图

运用对象池化技术可以显著地提升性能,尤其是当对象的初始化过程代价较大或者频率较高时。

Object pooling can offer a significant performance boost; it is most effective in situations where the cost of initializing a class instance is high, the rate of instantiation of a class is high.

结构

 

参与者

Reusable

  • 类的实例与其他对象进行有限时间的交互。

ReusablePool

  • 管理类的实例。

Client

  • 使用类的实例。

适用性

当以下情况成立时可以使用 Object Pool 模式:

  • 类的实例可重用于交互。
  • 类的实例化过程开销较大。
  • 类的实例化的频率较高。
  • 类参与交互的时间周期有限。

效果

  • 节省了创建类的实例的开销。
  • 节省了创建类的实例的时间。
  • 存储空间随着对象的增多而增大。

相关模式

  • 通常,可以使用 Singleton 模式实现 ReusablePool 类。
  • Factory Method 模式封装了对象的创建的过程,但其不负责管理对象。Object Pool 负责管理对象。

实现

实现方式(一):实现 DatabaseConnectionPool 类。

如果 Client 调用 ObjectPool 的 AcquireReusable() 方法来获取 Reusable 对象,当在 ObjectPool 中存在可用的 Reusable 对象时,其将一个 Reusable 从池中移除,然后返回该对象。如果池为空,则 ObjectPool 会创建一个新的 Reusable 对象。

复制代码
  1 namespace ObjectPoolPattern.Implementation1
  2 {
  3   public abstract class ObjectPool<T>
  4   {
  5     private TimeSpan _expirationTime;
  6     private Dictionary<T, DateTime> _unlocked;
  7     private Dictionary<T, DateTime> _locked;
  8     private readonly object _sync = new object();
  9 
 10     public ObjectPool()
 11     {
 12       _expirationTime = TimeSpan.FromSeconds(30);
 13       _locked = new Dictionary<T, DateTime>();
 14       _unlocked = new Dictionary<T, DateTime>();
 15     }
 16 
 17     public ObjectPool(TimeSpan expirationTime)
 18       : this()
 19     {
 20       _expirationTime = expirationTime;
 21     }
 22 
 23     protected abstract T Create();
 24 
 25     public abstract bool Validate(T reusable);
 26 
 27     public abstract void Expire(T reusable);
 28 
 29     public T CheckOut()
 30     {
 31       lock (_sync)
 32       {
 33         T reusable = default(T);
 34 
 35         if (_unlocked.Count > 0)
 36         {
 37           foreach (var item in _unlocked)
 38           {
 39             if ((DateTime.UtcNow - item.Value) > _expirationTime)
 40             {
 41               // object has expired
 42               _unlocked.Remove(item.Key);
 43               Expire(item.Key);
 44             }
 45             else
 46             {
 47               if (Validate(item.Key))
 48               {
 49                 // find a reusable object
 50                 _unlocked.Remove(item.Key);
 51                 _locked.Add(item.Key, DateTime.UtcNow);
 52                 reusable = item.Key;
 53                 break;
 54               }
 55               else
 56               {
 57                 // object failed validation
 58                 _unlocked.Remove(item.Key);
 59                 Expire(item.Key);
 60               }
 61             }
 62           }
 63         }
 64 
 65         // no object available, create a new one
 66         if (reusable == null)
 67         {
 68           reusable = Create();
 69           _locked.Add(reusable, DateTime.UtcNow);
 70         }
 71 
 72         return reusable;
 73       }
 74     }
 75 
 76     public void CheckIn(T reusable)
 77     {
 78       lock (_sync)
 79       {
 80         _locked.Remove(reusable);
 81         _unlocked.Add(reusable, DateTime.UtcNow);
 82       }
 83     }
 84   }
 85 
 86   public class DatabaseConnection : IDisposable
 87   {
 88     // do some heavy works
 89     public DatabaseConnection(string connectionString)
 90     {
 91     }
 92 
 93     public bool IsOpen { get; set; }
 94 
 95     // release something
 96     public void Dispose()
 97     {
 98     }
 99   }
100 
101   public class DatabaseConnectionPool : ObjectPool<DatabaseConnection>
102   {
103     private string _connectionString;
104 
105     public DatabaseConnectionPool(string connectionString)
106       : base(TimeSpan.FromMinutes(1))
107     {
108       this._connectionString = connectionString;
109     }
110 
111     protected override DatabaseConnection Create()
112     {
113       return new DatabaseConnection(_connectionString);
114     }
115 
116     public override void Expire(DatabaseConnection connection)
117     {
118       connection.Dispose();
119     }
120 
121     public override bool Validate(DatabaseConnection connection)
122     {
123       return connection.IsOpen;
124     }
125   }
126 
127   public class Client
128   {
129     public static void TestCase1()
130     {
131       // Create the ConnectionPool:
132       DatabaseConnectionPool pool = new DatabaseConnectionPool(
133         "Data Source=DENNIS;Initial Catalog=TESTDB;Integrated Security=True;");
134 
135       // Get a connection:
136       DatabaseConnection connection = pool.CheckOut();
137 
138       // Use the connection
139 
140       // Return the connection:
141       pool.CheckIn(connection);
142     }
143   }
144 }
复制代码

设计模式之美》为 Dennis Gao 发布于博客园的系列文章,任何未经作者本人同意的人为或爬虫转载均为耍流氓。

posted on 2014-04-16 09:06  HackerVirus  阅读(255)  评论(0编辑  收藏  举报