享元模式(Flyweight)就是把部分和整體的關系用樹形結構來表示,從而使客戶端能夠把一個個的部分對象和有他們組合起來的整體對象采用同樣的方式看待,他也是一個繼承的替代,其實具體的說,享元模式就是用時間交換了空間。用程序的運行速度來讀取是否重復的對象內容,然后不創建一個重復的對象來節省空間,于此同時就大大提高了程序的運行效率。
下面就簡單的原理圖:

然后通過一個字符的庫創建簡單的理解了一下享元模式,我們要創建一個字符庫,這樣就避免不了一些字符使我們想重復用的,這樣如果我們每次用都重新的創建一個對象,然后分配空間,那么對于好多重復的字符會明顯的浪費空間,這個時候就引入了享元模式。
首先創建一個字符的接口,定義了一個負責拿到所在實例中的字符的方法getName();如下:
~~~
package coml.designpattern.flyweight;
public interface Characters {
public String getName();
}
~~~
緊接著定義了一個公用的子類實現了這個接口,書中是做了N個子類實現,這里我就用了一個子類,并在Flyweight種也有區別,個人覺得這樣減少了代碼的復用:
~~~
package coml.designpattern.flyweight;
public class Character implements Characters {
private String name;
public Character(String name) {
this.name = name;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return this.name;
}
}
~~~
然后在Flyweight中定義創建字符的具體的方法和相關的邏輯:
~~~
package coml.designpattern.flyweight;
import java.util.ArrayList;
import java.util.List;
public class Flyweight {
private List list = new ArrayList();
public Characters getCharacter(String name) {
Characters characters = null;
for (int i = 0; i < list.size(); i++) {
characters = (Characters) list.get(i);
if (name.equals(characters.getName())) {
System.out.println(name + "不是第一次使用,未分配空間");
break;
} else {
characters = null;
}
}
if (characters == null) {
characters = new Character(name);
System.out.println(name + "第一次使用,并分配空間");
list.add(characters);
}
return characters;
}
}
~~~
定義了一個list,每次有新對象的時候就放進去,然后每次調用GetCharacter時候都會去遍歷整個list想要的對象有沒有創建好,如果有就不再創建,如果沒有在創建,書中這里是用了N個Characters的實現類,在if語句塊里面定義了N中情況,每一個字符就是一個對象,我這里就一個實現類,然后用不同的引用而已, 其實效果是一樣的,然后客戶端的調用:
~~~
package coml.designpattern.flyweight;
public class Client {
public static void main(String[] args) {
Flyweight flyweight = new Flyweight();
Characters study1 = flyweight.getCharacter("study");
Characters pattern = flyweight.getCharacter("pattern");
Characters study2 = flyweight.getCharacter("study");
Characters java = flyweight.getCharacter("java");
Characters study3 = flyweight.getCharacter("study");
Characters js = flyweight.getCharacter("js");
System.out.println(study1.getName() + "\t" + java.getName() + "\t"
+ study2.getName() + "\t" + pattern.getName() + "\t"
+ study3.getName() + "\t" + js.getName() + "\t");
}
}
~~~
輸出結果:
~~~
study第一次使用,并分配空間
pattern第一次使用,并分配空間
study不是第一次使用,未分配空間
java第一次使用,并分配空間
study不是第一次使用,未分配空間
js第一次使用,并分配空間
study java study pattern study js
~~~
這樣發現study雖然使用了三次但是他只創建了一次,如果使用N次,那么會很明顯的減少了空間的使用;
在數據庫連接池就是實際中的應用,先創建好一個池,每次有人要取得數據不會再像JDBC一樣創建一個新的連接,這樣減少了服務器端的壓力,提高了項目的性能;
使用享元模式可以大大節省空間,但是需要維護所有的享元對象,如果 要維護的享元很多,在查找的時候要消耗大量的時間,因此享元模式是典型的以時間來交換空間。
- 前言
- 前言(目錄、源碼、資料)
- (一)簡單工廠模式(SimpleFatory)
- (二)工廠方法模式(FactoryMethod)
- (三)抽象工廠模式(AbstractFactory)
- (四)創建者模式(Builder)
- (五)原型模式(Prototype)
- (六)單例模式(Singleton)
- (七)外觀模式(Facade)
- (八)適配器模式(Adapter)
- (九)代理模式(Proxy)
- (十)裝飾模式(Decorator)
- (十一)橋模式(birdge)
- (十二)組合模式(Composite)
- (十三)享元模式(Flyweight)
- (十四)模板方法模式(Template)
- (十五)觀察者模式(Observer)
- (十六)狀態模式(State)