software projects need costly object creations (database connections,
socket connections, large graphical objects etc.). This cost may be
about time and/or memory. Those objects may also be needed to be created
frequently. At that moment, Object/Resource Pool pattern comes to help.
Object Pool pattern:
- Reuses unused costly objects without re-creating those objects (e.g. books in a library).
- May create objects eagerly before they are needed, to manage application performance.
- May limit created number of objects to manage application performance and user access.
|Object Pool Class Diagram|
Client requests an
object (Reusable) from object pool. Object pool has a list of predefined
reusables and gives an available one from pool. For the client's point
of view, given reusable is a new object but it is probably (object
creation strategies will be told later) a pre-created object with a new
object's field values. For the optimum performance, client should notify
object pool when reusable is no longer needed. Just in case client
doesn't notify, object pool may define a timeout for each created
reusable. Object pool must also have a synchronization mechanism for
reusable serving, especially on multithreaded or multiuser applications.
When to use/Trade offs:
If objects are not
costly, object pool pattern should not be used because this pattern
needs clients to inform object pool (brings extra code complexity) and
object creation management code (synchronization of pool, object
creation limitation strategy etc.). This extra management code also
brings a little performance loss. If performance gain of reusable object
usage is bigger than extra management code performance loss, and
application must frequently create those reusable objects, object pool
pattern is recommended to be used.
Object pool limit:
memory is limited and/or maximum number of clients are needed to be
restricted, an object number limit value may be defined for object pool
- If there is no restriction, limit value is not needed (unlimited pool).
all object pool list is in use, new objects may be created (expanding
pool) or client may be enforced to waiting (fixed pool).
Empty object pool strategy:
- If application
startup is performed infrequently and startup time is not very
important, object pool list objects may be created at the startup (eager
- If no restrictions exist, no objects are needed to be created eagerly (lazy creation).
- Some number of
objects may be created eagerly, others may be created lazily according
to the application parameters (mixed creation).
- If object pool is expanding, create a new object and return it.
- If object pool is not expanding, return null or enforce client to wait until an object is ready to be given.
Unused object strategy:
pool should have a synchronization mechanism for object serving.
Otherwise, especially on multiuser systems, pooling system may fail.
Returning object strategy:
of the pool objects may be lower than expected in some cases. Object
pool may have a pool object removing strategy (i.e. descreasing object
limit) for increasing performance.
should return pool objects back to the pool after their job is
completed. But pool code can't control this and poor client code may
return pool objects. For this situation, object pool may have a timer
mechanism for given but unused pool objects.
According to the
project requirements, some of those strategies or mixed versions should
be selected and implemented for object pool. But "reusing available
objects" principle is the key and can not be changed for any
Example Implementations will exist on the next post.