您的位置:首页 > 移动开发 > Objective-C

Object Pool Design Pattern

2013-11-26 15:53 369 查看


Intent

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, and the number of instantiations in use at any one time is low.


Problem

Object pools (otherwise known as resource pools) are used to manage the object caching. A client with access to a Object pool can avoid creating a new Objects by simply asking the pool for one that has already been instantiated instead. Generally the pool will
be a growing pool, i.e. the pool itself will create new objects if the pool is empty, or we can have a pool, which restricts the number of objects created.

It is desirable to keep all Reusable objects that are not currently in use in the same object pool so that they can be managed by one coherent policy. To achieve this, the Reusable Pool class is designed to be a singleton class.


Discussion

The Object Pool lets others "check out" objects from its pool, when those objects are no longer needed by their processes, they are returned to the pool in order to be reused.

However, we don't want a process to have to wait for a particular object to be released, so the Object Pool also instantiates new objects as they are required, but must also implement a facility to clean up unused objects periodically.


Structure

The general idea for the Connection Pool pattern is that if instances of a class can be reused, you avoid creating instances of the class by reusing them.





Reusable
 - Instances of classes
in this role collaborate with other objects for a limited amount of time, then they are no longer needed for that collaboration.

Client
 - Instances of classes
in this role use Reusable objects.

ReusablePool
 - Instances of
classes in this role manage Reusable objects for use by Client objects.

Usually, it is desirable to keep all 
Reusable
 objects
that are not currently in use in the same object pool so that they can be managed by one coherent policy. To achieve this, the
Reusable
Pool
class is designed to be a singleton class. Its constructor(s) are private, which forces other classes to call its getInstance method to get the one instance of the
ReusablePool
 class.

A Client object calls a 
ReusablePool
 object's 
acquireReusable
 method
when it needs a
Reusable
 object. A 
ReusablePool
 object
maintains a collection of 
Reusable
 objects. It uses
the collection of 
Reusable
 objects to contain a pool
of 
Reusable
 objects that are not currently in use.

If there are any 
Reusable
 objects in the pool when
the 
acquireReusable
 method is called, it removes
Reusable
 object from the pool and returns it. If
the pool is empty, then the 
acquireReusable
 method
creates a 
Reusable
 object if it can. If the
acquireReusable
 method
cannot create a new 
Reusable
 object, then it waits
until a
Reusable
 object is returned to the collection.

Client objects pass a 
Reusable
 object to a 
ReusablePool
 object's 
releaseReusable
method
when they are finished with the object. The 
releaseReusable
 method
returns a
Reusable
 object to the pool of 
Reusable
 objects
that are not in use.

In many applications of the Object Pool pattern, there are reasons for limiting the total number of 
Reusable
 objects
that may exist. In such cases, the 
ReusablePool
 object
that creates 
Reusable
 objects is responsible for
not creating more than a specified maximum number of 
Reusable
 objects.
If 
ReusablePool
 objects are responsible for limiting
the number of objects they will create, then the 
ReusablePool
 class
will have a method for specifying the maximum number of objects to be created. That method is indicated in the above diagram as setMaxPoolSize.


Example

Do you like bowling? If you do, you probably know that you should change your shoes when you getting the bowling club. Shoe shelf is wonderful example of Object Pool. Once you want to play, you'll get your pair (
aquireReusable
)
from it. After the game, you'll return shoes back to the shelf (
releaseReusable
).




Check list

Create 
ObjectPool
 class
with private array of 
Object
s inside
Create 
acquare
 and 
release
 methods
in ObjectPool class
Make sure that your ObjectPool is Singleton


Rules of thumb

The Factory Method pattern can be used to encapsulate the creation logic for objects. However, it does not manage them after their creation, the object pool pattern keeps track of the objects it creates.

Object Pools are usually implemented as Singletons.
下面是详细实现代码,在代码里并没有对设置数据池的最大最小数量、客户端数进行设置,代码的意图在于通过设计一个简单的数据池来表达资源池的概念:

// ObjectPool Class

public abstract class ObjectPool<T> {
private long expirationTime;

private Hashtable<T, Long> locked, unlocked;

public ObjectPool() {
expirationTime = 30000; // 30 seconds
locked = new Hashtable<T, Long>();
unlocked = new Hashtable<T, Long>();
}

protected abstract T create();

public abstract boolean validate(T o);

public abstract void expire(T o);

public synchronized T checkOut() {
long now = System.currentTimeMillis();
T t;
if (unlocked.size() > 0) {
Enumeration<T> e = unlocked.keys();
while (e.hasMoreElements()) {
t = e.nextElement();
if ((now - unlocked.get(t)) > expirationTime) {
// object has expired
unlocked.remove(t);
expire(t);
t = null;
} else {
if (validate(t)) {
unlocked.remove(t);
locked.put(t, now);
return (t);
} else {
// object failed validation
unlocked.remove(t);
expire(t);
t = null;
}
}
}
}
// no objects available, create a new one
t = create();
locked.put(t, now);
return (t);
}

public synchronized void checkIn(T t) {
locked.remove(t);
unlocked.put(t, System.currentTimeMillis());
}
}

//The three remaining methods are abstract
//and therefore must be implemented by the subclass

public class JDBCConnectionPool extends ObjectPool<Connection> {

private String dsn, usr, pwd;

public JDBCConnectionPool(String driver, String dsn, String usr, String pwd) {
super();
try {
Class.forName(driver).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
this.dsn = dsn;
this.usr = usr;
this.pwd = pwd;
}

@Override
protected Connection create() {
try {
return (DriverManager.getConnection(dsn, usr, pwd));
} catch (SQLException e) {
e.printStackTrace();
return (null);
}
}

@Override
public void expire(Connection o) {
try {
((Connection) o).close();
} catch (SQLException e) {
e.printStackTrace();
}
}

@Override
public boolean validate(Connection o) {
try {
return (!((Connection) o).isClosed());
} catch (SQLException e) {
e.printStackTrace();
return (false);
}
}
}

JDBCConnectionPool will allow the application to borrow and return database connections:

public class Main {
public static void main(String args[]) {
// Do something...
...

// Create the ConnectionPool:
JDBCConnectionPool pool = new JDBCConnectionPool(
"org.hsqldb.jdbcDriver", "jdbc:hsqldb://localhost/mydb",
"sa", "secret");

// Get a connection:
Connection con = pool.checkOut();

// Use the connection
...

// Return the connection:
pool.checkIn(con);

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: