Look at the application of Design Pattern (6) from a ConnectionPool implementation (6)
How to reuse different resources? Let us first examine our ConnectionPool implementation.
1. The POOLING algorithm is implemented by Connectionman. It needs to entrust ConnectionFactory to create a Connection object to specifically
2. ConnectionFactory is responsible for establishing a connection. It encapsulates how to establish a connection
3. PooledConnection is responsible for encapsulating the Connection object, modifying a method related to POOLING and delegate other methods.
4. Connectionman2ConnectionPool is responsible for using PooledConnection to convert a ConnectionMan that cannot be misleasted to users and opaque users. ConnectionPool.
First, the PooledConnection cannot be reused. It only implements the Connection interface and rewrites the close () method. For an unknown resource, we naturally write an implementation in advance, which cannot be understood in addition to which method is responsible for release.
Second, Connectionman2ConnectionPool, because it uses PooledConnection directly, and cannot be reused for different resources POOL. In other words, we must write package classes and conversion classes for different resources.
ConnectionFactory is an interface, we can write a more Generic ResourceFactory to let different resourcepool reuse it.
Reuse the pooling algorithm is the key. Can I rely on we have extracted all the details related to specific Resource. In this algorithm, what is related to specific resources? Resource creation is naturally one, we have taken it with an Abstract Factory. Another resource release is related to specific resources. We release Connection with a Close () method. But for other resources, maybe it is a release () method, destroy () method, or even no way.
So, in order to reuse the POOLING algorithm, we also need to release abstract resources. A resourceCollector's interface should be able to complete this work. (If you say, ConnectionFactory is Abstract Factory Pattern, why there is no Pattern for ResourceCollector in GOF's book?)
Ok, before writing the code, there is still something to clarify:
Many C programmers believe that C GP is a more useful technology than OO. In fact, the most important Function Object of the GP, and the interface-oriented interface programming in OO is just a pair of twin brothers. Template is more efficient than current Java's OO at: 1, high efficiency. 2, reduce many types of forced conversion (DOWNCAST).
And many Java programmers believe that Java does not need GP, because all GPs can do, OO can do. If GP can have Vector
It is said that the current Java syntax is to use the current Java syntax, even if we can write a reusable ResourcePool framework, it is also safe to secure the program. Users need to explicitly join DOWNCAST to use this framework. Therefore, since we are just academic discussions, let us use the syntax similar to Generic Java here to make our program more beautiful.
The first is the ResourceFactory interface:
Public Interface ResourceFactory
R createresource ();
}
ResourceCollector interface:
Public Interface ResourceCollector
Void ClosResource (R r);
}
The resourceman interface is still a friendly interface for realizes, but needs to be encapsulated to be handed over to the client.
Public Interface Resourceman
R getresource ()
Throws throwable;
Void clear ();
Void ReleaseResource (R r);
}
Below is an implementation of a resourceman using the Pooling logic of our ConnectionManImpl.
Public Class ResourceManImpl
Typedef resourceman
Typedef resourcefactory
Typedef ResourceCollector
PRIVATE FINAL FACTORY;
PRIVATE FINAL COLLECTOR;
PRIVATE INT Client;
Private final vector
PRIVATE FINAL INT MAXCLIENTS;
Static Public Man Instance (Factory F, Collector C, INT M) {
Return New ResourceManImpl (f, c, m);
}
Private ResourceManImpl (Factory F, Collector C, INT M)
{
THIS.MAXCLIENTS = M;
this.factory = f;
THIS.COLLEctor = C;
}
Public Final Synchronized Void ReleaseResource (r resource)
{
Freelist.addelement (resource);
Client -;
NOTIFY ();
}
Public Final Synchronized R getResource ()
Throws throwable
{
R ret;
If there is R in pool
Remove a R r from the pool;
CLIENTS ;
RET = R;
Otherwise, if Clients R = factory.createresource (); CLIENTS ; RET = R; Otherwise, Wait () until there is idle R in Pool Return Ret; } Public synchronized void clear () { Resource R in each re-free List: Collector. ClosResource (R); freeelist.removeallelements (); } } Oh, this way, your company can hire a few people who only drilled various Pooling algorithms, let them do anything, only write different Pooling algorithms, which is the implementation of different resourceman. For a specific resource, we only need to give the implementation of ResourceFactory and ResourceCollector, you can instantiate a resourceman, then write the package class and transition class according to the specific resources, (here, the package class is slightly troublesome, but also However, it is some delegation and several special functions related to pooling), and a pool of that specific resource can be released. You can even set up a company, specifically selling all kinds of Pool to other development companies. So, suppose you have five types of pooling algorithms, three resources that need Pool, each resource has four creation methods, two release methods, then you can settle arbitrarily, to form 5 * 3 * 4 * 2 = 90 kinds of different pool. This is the power-oriented interface programming! You no longer develop only a process of executing, no longer doing some modifications to modify the modification and extension over some classes. You are inserting a socket and plug together! As long as the interfaces are consistent, you can any combination. Wonderful? More wonderful, I don't know if you notice that there is no implementation, there is no hypothesis for a particular situation. You will not sacrifice the efficiency of the function you want to use because of our care of a function you can't use. You won't get a 1000 line code, and 900 rows is to achieve the function you can't use. Of course, it is not necessary to say that efficiency is not affected by taking care of the generality. Note that the ResourceManImpl.clear () method. The purpose of this method is to release all idle resources in the pool and empty the resource pool. Our current implementation is to traverse all resources in the pool, call the ResourceCollector.closeSource method to release. Then clear the resource pool. This is very good for Connection Pool. We only need to implement a simple ConnectionCollector, just like this: Public Class ConnectionCollector Implements ResourceCollector Public void closResource (Connection Conn) { CONN.CLOSE (); } PRIVATE CONNECTIONCOLLECTOR () {} Private static final test.res.ResourceCollector Public static test.res.ResourceCollector } Then hand it over to a class we have selected Resourceman. However, in fact, not all resources need to be explicitly released. For example, Thread, we only need to remove the reference to this Thread, which will eventually be released by the garbage collector. We do not need to traverse the idle thread to release them. Of course, you can pass this Resourceman a resourcecollector, in its closeresource method, nothing. In this way, the function is still implemented. However, this method is in that it turns a Clear () method that can be O (1) into O (N). Although Java is not more than efficient, if you don't need a call overhead for a virtual function, it is too worried. But increase the complexity of a method is always a very very bad thing. Moreover, (just imagined) may have some special resources, it must be based on some logic order? How to solve this strategic problem that is released for all idle resources? If you want to write a Pooling algorithm, you don't need to call resource release, or reside a POOLING, it is obviously not good. How do he reuse his smart Pooling algorithm? COPY PASTE? I believe the first sense of many people is still: reload clear (). But just as we say in front: First: This will produce too many classes Second: The location of the unique parent class is occupied. A class in Java can only have a parent class. If your framework requires users to inherit your class, you will also deprive the rights of users inherit other classes. Third: The coupling between the parent class class is the enemy of a large system. Once the parent class is released, I want to change (for example, add a private way), it is very difficult! (Because you don't know if a subclass has already used this function signature.) How to do it? Still interte! We can join an interface responsible for recovering all resources. Then achieve anything else to THREAD POOL. (Guaranteed the calculation complexity of Clear (1); re-realized the resource for imaginary resources; re-real sequential recycling classes Resources such as Connection. This interface is similar to this: Public Interface ResourcesCollector Public Void Collect (Collection } The code after the revised ResourceManImpl is like this: Public Class ResourceManImpl Typedef resourceman Typedef resourcefactory Typedef ResourcesCollector PRIVATE FINAL FACTORY; PRIVATE FINAL COLLECTOR; PRIVATE INT Client; Private final vector PRIVATE FINAL INT MAXCLIENTS; Static Public Man Instance (Factory F, Collector C, INT M) { Return New ResourceManImpl (f, c, m); } Private ResourceManImpl (Factory F, Collector C, INT M) { THIS.MAXCLIENTS = M; this.factory = f; THIS.COLLEctor = C; } Public Final Synchronized Void ReleaseResource (r resource) { Freelist.addelement (resource); Client -; NOTIFY (); } Public Final Synchronized R getResource () Throws throwable { R ret; If there is R in pool Remove a R r from the pool; CLIENTS ; RET = R; Otherwise, if Clients R = factory.createresource (); CLIENTS ; RET = R; Otherwise, Wait () until there is idle R in Pool Return Ret; } Public synchronized void clear () { Collector. Collect (Free); Freelist.removeallelements (); } } The implementation of the resourcescollector for Thread Pool is like this: Public Class NopResourcesCollector Implements ResourcesCollector Private static final nopResourcesCollector Singleton = New NopResourcesCollector (); PRIVATE NOPRESOURESCOLLECTOR () {} Public Void Collect (Collection Public Static ResourcesCollector Return Singleton; } } (Excellent: The NOPResourcesCollector here is a bit special. It is not a class with type parameters. Instead, it is a normal class, but it achieves any resourcescollector This special syntax is not supported by C Template and Generic Java. It is a "fun direction" in the laboratory. Its role is to avoid multiple Singleton instances. For all resource R, whether it is Connection, Thread or what else, you share a NopResourceScollector. This is safe, because no matter what, NopResourcesCollectors don't do anything. ) The implementation of the regular resourcescollector such as Connection Pool is true: Public Class LinearResourcesCollector Private final resourcecollector Private LinearResourcesCollector (ResourceCollector THIS.C = C; } Public Void Collect (Collection Each R in Collection C.Collect (R); } Public Static ResourcesCollector Return New LinearResourcesCollector } }