Look at the application of Design Pattern (5) from a ConnectionPool implementation (5)
OK, now we have already dropped the task of encapsulated connection from the developers of ConnectionPool. They simply implement an auxiliary ConnectionMAN interface, and the remaining things are done by the PooledConnection class and the Connectionman2ConnectionPool class.
Below, let's take a closer look at the ConnectionManImpl class:
Public Class ConnectiomanImpl Implements ConnectionMan {
Public synchronized connection getConnection () {
CONNECTION RET;
If there is a Connection in pool
Remove a connection conn from the pool;
CLIENTS ;
Ret = conn;
Otherwise, if Clients CONN = NewConnection (); CLIENTS ; Ret = conn; Otherwise, Wait () until there is idle connection in pool Return conn; } Public Synchronized Void CloseConnection (Connection Conn) { Pool.Add (conn); Clients -; NOTIFY (); } PRIVATE connection newconnection () { // Generate a Connection from DriverManager using username, password, database URL, etc. } // Some user names, passwords, and the like to establish the information of Connection. } Have you noticed it? In addition to writing pooling algorithms, Connectionman's implementation is concerned about how to create Connection. This creation of a Connection process is not always the same. We may generate a Connection from DRIVERMANAGER, or it is also possible to generate connection from DataSource; it may be generated by username, password, or it is also possible to generate with Connection String. The same POOLING logic, may need to handle different ways of generating connection, the same way to generate Connection may require different POOLING logic. Therefore, it seems not a good way to generate coupling of Pooling logic and Connection. So how do you solve this problem? In the POOLING algorithm, you need to generate a CONNECTION in the appropriate moment! "Do ConnectionManImpl into an abstract class, then require each subclass to override the NewConnection () method. Senior programmer Zhang San did not say. Yes, this is indeed an intuitive and effective way. For the same POOLING algorithm, you only need Subclass its own subclasses, develop your own Connection generation, you can reuse the logic of the parent class. This is called Template Method Pattern. However, telling the truth, the individual doesn't like this pattern. From this case, if we have five types of Pooling algorithms, three connection generating methods, then we need to write fifteen subclasses. Too flexible. Moreover, realization of the strong coupling relationship between the parent and son caused by inheritance, and it is also annoying. A unusual change of the parent class may no longer work. Then. . . . right! Let us abstract the generation of Connection. Use Abstract Factory. First define a Factory interface. Public interface connectFactory { PUBLIC Connection CreateConnection () THROWS SQLEXCEPTION; } Then change our ConnectionManImpl to entrust the work that generates the CONNECTION to a ConnectionFactory. Public Class ConnectionMnImpl Implements ConnectionMan { PRIVATEFACTORY; PRIVATE FINAL INT MAXCONN Private ConnectionManImpl (ConnectionFactory Factory, Int max) { THIS.FACTORY = Factory; THIS.MAXCONN = Max; } Static Public ConnectionMan Instance (ConnectionFactory Factory, Int max) { Return New ConnectionManImpl (Factory, Max); } Public final synchronized connection getConnection () Throws SQLEXCEPTION { If there is a Connection in pool Remove a connection conn from the pool; CLIENTS ; Return conn; Otherwise, if Clients Conn = factory.createConnection (); CLIENTS ; Return conn; Otherwise, Wait () until there is idle connection in pool } / / Others are the same as before. } Look at an example ConnectionFactory implementation: Public Class ConnectionFactoryImpl { Private connectionFactoryImpl () {} Static Public ConnectionFactory Instance (Final String USER, FINAL STRING PWD, Final String Url, Final String Driver THROWS SQLEXCEPTION, CLASSNOTFOUNDEXCEPTION { Final Class Driverclass = Class.Forname (driver); Return New ConnectionFactory () { PRIVATE FINAL CLAEPER = DriverClass; Public Final Connection CreateConnection () Throws sqlexception { Return DriverManager.getConnection (URL, User, PWD); } } } } Finally, look at how we put a ConnectionMan, a connectionFactory into a connectionpool. Public class testConnectionPool { Public Static Void Test (String User, String PWD, String Url, String Driver) Throws java.sql.sqlexception, classnotfoundexception { Final ConnectionPool Pool = Connectionman2ConnectionPool.Decorate ConnectionManImpl.instance (ConnectionFactoryImpl.instance (User, PWD, URL, DRIVER), 1000) ); } } Ok, this chapter, we show how to separate the POOLING logic in ConnectionManImp and the logic generated by the Connection to achieve a greater code reuse. Thinking: Pooling, as a technology, not just Application of ConnectionPool, other technologies such as Thread Pool and any resource that requires certain overhead, can apply this technology. So, how can we reuse a pooling algorithm to different pools such as Connection Pool, Thread Pool? How can I say: "Give me a Pooling algorithm written by Li, I have to take it to buffer my thread." Instead, "Li Si, your connection poibility is a good writing, can I give me Thread pooling a one?"