享元模式

享元模式是对象的结构模式。享元模式以共享的方式高效地支持大量的细粒度对象。

单纯享元模式所涉及到的角色如下:
  ●  抽象享元(Flyweight)角色 :给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。
  ●  具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。
  ●  享元工厂(FlyweightFactory)角色 :本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。


 

享元模式由于其共享特性,可以使用在任何池化的操作中,如线程池、数据库连接池等。数据库连接池是享元模式的一个典型应用。在该应用中,需要一个连接池工厂类ConnectPool,它是多个连接Connection的聚集,其结构如图12-26所示。

享元模式 

连接池工厂类ConnectPool具有一个数据集合对象pool,它在构造函数中进行初始化。该类提供了一个单例的工厂类,以防止重复创建该工厂实例,并提供取得连接getConnection()和释放连接freeConnection()函数来分别从共享池中取得和释放一个连接。

其源代码如程序12-47所示。

程序12-47  连接池实例ConnectionPool.java

 
 
  1. package structure.flyweight;  
  2.  
  3. import java.sql.Connection;  
  4. import java.sql.SQLException;  
  5. import java.util.Vector;  
  6.  
  7. /**  
  8.  * @author liuzhongbing  
  9.  * 享元模式-连接池实例  
  10.  */ 
  11. public class ConnectionPool {  
  12.  
  13.     private Vector<Connection> pool;  
  14.  
  15.     private String url = "jdbc:mysql://localhost:3306/test";  
  16.     private String username = "root";  
  17.     private String password = "";  
  18.     private String driverClassName = "com.mysql.jdbc.Driver";  
  19.  
  20.     /**  
  21.      * 连接池的大小,也就是连接池中有多少个数据库连接  
  22.      */ 
  23.     private int poolSize = 100;  
  24.  
  25.     private static ConnectionPool instance = null;  
  26.  
  27.     /**  
  28.      * 私有的构造方法,禁止外部创建本类的对象,要想获得本类的对象,  
  29.      通过<code>getIstance</code>方法  
  30.      * 使用了设计模式中的单子模式  
  31.      */ 
  32.     private ConnectionPool() {  
  33.         pool = new Vector<Connection>(poolSize);  
  34.         // 在连接池中创建初始设置的数据库连接  
  35.         Connection conn = null;  
  36.         for (int i = 0; i < poolSize; i++) {  
  37.             try {  
  38.                 Class.forName(driverClassName);  
  39.                 conn = java.sql.DriverManager.getConnection(url, 
  40. username, password);  
  41.                 pool.add(conn);  
  42.             } catch (ClassNotFoundException e) {  
  43.                 e.printStackTrace();  
  44.             } catch (SQLException e) {  
  45.                 e.printStackTrace();  
  46.             }  
  47.  
  48.         }  
  49.     }  
  50.       
  51.     /**  
  52.      * 返回连接到连接池中  
  53.      */ 
  54.     public synchronized void release(Connection conn) {  
  55.         pool.add(conn);  
  56.     }  
  57.  
  58.     /**  
  59.      * 关闭连接池中的所有数据库连接  
  60.      */ 
  61.     public synchronized void closePool() {  
  62.         for (int i = 0; i < pool.size(); i++) {  
  63.             try {  
  64.                 ((Connection) pool.get(i)).close();  
  65.             } catch (SQLException e) {  
  66.                 e.printStackTrace();  
  67.             }  
  68.             pool.remove(i);  
  69.         }  
  70.     }  
  71.  
  72.     /**  
  73.      * 返回当前连接池的一个对象  
  74.      */ 
  75.     public static ConnectionPool getInstance() {  
  76.         if (instance == null) {  
  77.             instance = new ConnectionPool();  
  78.         }  
  79.         return instance;  
  80.     }  
  81.  
  82.     /**  
  83.      * 返回连接池中的一个数据库连接  
  84.      */ 
  85.     public synchronized Connection getConnection() {   
  86.         if (pool.size() > 0) {  
  87.             Connection conn = pool.get(0);  
  88.             pool.remove(conn);  
  89.             return conn;  
  90.         } else {  
  91.             return null;  
  92.         }  
  93.     }  

要使用该连接池,只需要创建一个连接池的实例pool,然后使用getConnection()来取得一个连接执行SQL查询,最后使用freeConnection()来释放连接即可。其源代码如程序12-48所示。

程序12-48  连接池测试类ConnectionPoolTest.java

 
 
  1. package structure.flyweight;  
  2.  
  3. import java.sql.Connection;  
  4. import java.sql.ResultSet;  
  5. import java.sql.Statement;  
  6.  
  7. public class ConnectionPoolTest {  
  8.  
  9.     public static void main(String[] args) throws Exception {  
  10.         String sql = "select id,name,phone from guestmessage";  
  11.         ConnectionPool pool = ConnectionPool.getInstance();  
  12.         for (int i = 0; i < 100; i++) {  
  13.             Connection conn = pool.getConnection();  
  14.             Statement stmt = conn.createStatement();  
  15.             ResultSet rs = stmt.executeQuery(sql);  
  16.             while (rs.next()) {  
  17.             }  
  18.             rs.close();  
  19.             stmt.close();  
  20.             pool.release(conn);  
  21.         }  
  22.         pool.closePool();  
  23.     }  

通过以上连接池的管理,实现了数据库连接的共享,不需要每一次取得连接时都重新创建,因为节省了重复创建数据库连接的开销,使得程序的性能大幅提升。

你可能感兴趣的:(享元模式)