引言:
享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。我们在日常开发中经常遇到线程池的概念。
所谓池就是一些对象集合,为了避免对象无限被创建,并且待创建的对象都是相似的。享元模式可以实现对象的细粒度的控制。
一.享元模式:
FlyWeightFactory负责创建和管理享元单元,当一个客户端请求时,工厂需要检查当前对象池中是否有符合条件的对象,如果有,就返回已经存在的对象,如果没有,则创建一个新对象,FlyWeight是超类。
二.理解享元模式
我们以简单的map集合来作为对象池,享元模式基本逻辑如下所示:
1)一个key标识一个对象,
2)从对象池中查找key,如果找到则返回,否则执行3)。
3)创建新对象,并放入对象池中。
注:最核心的就是一个对象的内部状态可以通过外部状态来标识。就是通过特殊的辨识来查找对象,他们之间是对应关系。
private Map<String, Object> map = new HashMap<String, Object>
public Object get(String key) {
if(map.containsKey(key)) {
return map.get(key);
}
Object obj = new Object();
map.put(key, obj);
return obj;
}
三.开发案例
一提到共享池,我们很容易联想到Java里面的JDBC连接池,想想每个连接的特点,我们不难总结出:适用于作共享的一些个对象,他们有一些共有的属性,就拿数据库连接池来说,url、driverClassName、username、password及dbname,这些属性对于每个连接来说都是一样的,所以就适合用享元模式来处理,建一个工厂类,将上述类似属性作为内部数据,其它的作为外部数据,在方法调用时,当做参数传进来,这样就节省了空间,减少了实例的数量。
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Vector;
import cn.search.Util.XMLUtils;
/**
* 该线程池是一个单例对象
* @author cristo
*
*/
public class ConnectionManager {
public static Vector<Connection> pool=null;
public int initConnectionSize=5;
//已经创建的个数
private static int hasCreatedConnection=0;
//还在线程池中连接
private static int ConnectionInPool=0;
//实例化
private static ConnectionManager manager=new ConnectionManager();
/**
* 得到管理器
* @return
*/
public static ConnectionManager getManager(){
return manager;
}
private ConnectionManager(){
try {
init();
} catch (Exception e) {
throw new RuntimeException("mysql数据库初始化出错...");
}
}
/**
* 初始化连接池
* @throws Exception
*/
public void init() throws Exception{
pool = new Vector<Connection>(initConnectionSize);
hasCreatedConnection=initConnectionSize;
ConnectionInPool=initConnectionSize;
for(int i=0;i<initConnectionSize;i++){
Connection con=createConnection();
pool.add(con);
}
}
/**
* 从线程池中取连接
* @return
* @throws Exception
*/
public synchronized Connection getConnection() throws Exception{
Connection con=null;
if(ConnectionInPool>0){
con=pool.remove(0);
ConnectionInPool--;
return con;
}
else{
con=createConnection();
}
return con;
}
/**
* 返回连接
* @param con
*/
public synchronized void release(Connection con){
if(con==null)
return;
pool.add(con);
ConnectionInPool++;
}
/**
* 创建连接,从配置文件中读取配置信息
* @return
* @throws Exception
*/
public Connection createConnection() throws Exception{
Connection con=null;
XMLUtils.parseArgs();
String driver = XMLUtils.getAsString("driver");
String url = XMLUtils.getAsString("url");
String user = XMLUtils.getAsString("user");
String pW =XMLUtils.getAsString("password");
Class.forName(driver).newInstance();
con = DriverManager.getConnection(url,user,pW);
return con;
}
public static void main(String[]args){
Thread t=new Thread(){
ConnectionManager manager=ConnectionManager.getManager();
public void run() {
Connection con=null;
try {
con = manager.getConnection();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(con);
manager.release(con);
};
};
//访问
t.start();
}
}
四.总结
在实际开发中涉及到数据库这些共用资源时,一般都需要考虑建立一个资源池,以便避免程序无限创建对象,导致系统性能下降,内存损耗过大。