在说明享元模式的定义之前我们先来看个图,意会一下。
我相信与很多人一眼就能看懂,享元模式的优点也一目了然。
享元模式的官方定义是运用共享技术有效的支持大量细粒度的对象。其实就是使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。
就像上面图中,颜色和字体共享显示(但做事一种归类划分也没问题,让同类事物共享资源)。
它主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。类图借用一下啦!
FlyWeightFactory负责创建和管理享元单元,当一个客户端请求时,工厂需要检查当前对象池中是否有符合条件的对象,如果有,就返回已经存在的对象,如果没有,则创建一个新对象,FlyWeight是超类。
在javaSE中有很多经典的应用,说到这个模式,不得不提一下数据库的JDBC连接池,对数据库连接池来说,url、driverClassName、username、password及dbname,这些属性对于每个连接来说都是一样的,所以适合用享元模式来处理,建一个工厂类ConnectionPool ,将上述类似属性作为内部数据,其它的作为外部数据,在方法调用时,当做参数传进来,通过连接池的管理,实现了数据库连接的共享,不需要每一次都重新创建连接,节省了数据库重新创建的开销,提升了系统的性能!看代码:
package com.freedom.flyweight;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Vector;
public class ConnectionPool {
private Vector<Connection> pool;
/*共享属性*/
private String url = "jdbc:mysql://localhost:3306/test";
private String username = "root";
private String password = "root";
private String driverClassName = "com.mysql.jdbc.Driver";
private int poolSize = 100;
// private static ConnectionPool instance = null;
Connection conn = null;
/*构造方法,做一些初始化工作*/
private ConnectionPool() {
pool = new Vector<Connection>(poolSize);
for (int i = 0; i < poolSize; i++) {
try {
Class.forName(driverClassName);
conn = DriverManager.getConnection(url, username, password);
pool.add(conn);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/* 返回连接到连接池 */
public synchronized void release() {
pool.add(conn);
}
/* 返回连接池中的一个数据库连接 */
public synchronized Connection getConnection() {
if (pool.size() > 0) {
Connection conn = pool.get(0);
pool.remove(conn);
return conn;
} else {
return null;
}
}
}
小结:享元模式适用于作共享的一些个对象,他们有一些共有的属性。
问题来了,上面的代码是不是有点像大力模式呢?它们有什么区别呢?
享元模式可以理解成一组共享的对象集合,下面就是一个简单的享元设计模式,甚至可以说是工厂模式了,呵呵,工厂模式目的是将具体创建对象的过程由工厂方法提供,用户只需要知道抽象类型即可。但这个例子就不要纠结成工厂模式了)
package com.freedom.flyweight;
import java.util.HashMap;
import java.util.Map;
public class FlyWeight {
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;
}
public static void main(String[] args) {
FlyWeight fw = new FlyWeight();
fw.map.put("test", "freedom");
System.out.println(fw.get("test"));
}
}
单例模式
package com.freedom.flyweight;
public class Singleton {
private static Singleton instance = null;
private String name;
private Singleton(String name){
this.name = name;
}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton("freedom");
}
return instance;
}
public static void main(String[] args) {
System.out.println(Singleton.getInstance().name);
}
}
看完代码的话区别就不要运用多说了,享元设计模式是一个类有很多对象,而单例是一个类仅一个对象;享元模式是为了节约内存空间,提升程序性能(避免大量的new操作);而单例模式则主要是出于共享状态的目的。
最后再来总结一下享元模式的优缺点:
优点:在于它大幅度地降低内存中对象的数量。但是,它做到这一点所付出的代价也是很高的。
缺点:1.使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。
2.将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。
Finish!
源码下载:http://download.youkuaiyun.com/detail/github_22022001/8331775