概念:
享元模式(Flyweight Pattern)是一種軟件設計模式。它使用共享物件,用來儘可能減少內存使用量以及分享資訊給儘可能多的相似物件;它適合用於只是因重複而導致使用無法令人接受的大量內存的大量物件。通常物件中的部分狀態是可以分享。常見做法是把它們放在外部數據結構,當需要使用時再將它們傳遞給享元。
經典應用場景:
來複習下Java中String類型的特性:String類型的對象一旦被創造就不可改變;當兩個String對象所包含的內容相同的時候,JVM只創建一個String對象對應這兩個不同的對象引用。讓我們來驗證實下着兩個特性吧
先來驗證下第二個特性:
public class TestPattern {
public static void main(String[] args){
String n = "Java design"; String m = "Java design"; System.out.println(n==m); m=m+" pattern"; System.out.println(n==m);
}
}
這段代碼會告訴你n==m是true,這就說明了在JVM中n和m兩個引用了同一個String對象。之後在系統輸出之前加入一行代碼”m=m+" pattern";”,這時候n==m結果爲false,剛纔兩個還是引用的對象,已經不同了?原因就是在執行後添加語句時,m指向了一個新創建的String對象,而不是修改引用的對象。
JAVA String類型的設計避免了在創建N多的String對象時產生的不必要的資源損耗,可以說是享元模式應用的範例,下面來看看怎麼在自己的程序中使用享元模式。
實現:
在享元模式中,由於要產生各種各樣的對象,所以在Flyweight(享元)模式中常出現Factory模式。Flyweight的內部狀態是用來共享的,Flyweight factory負責維護一個對象存儲池(Flyweight Pool)來存放內部狀態的對象。Flyweight模式是一個提高程序效率和性能的模式,會大大加快程序的運行速度.應用場合很多。
案例:
項目需要建立城市地區數據,包括城市名,上級轄區等。
Area 類:
public abstract class Area { private String name; public abstract void displayName(); public abstract Area setAdminArea(Area area); public abstract Area getAdminArea(); public Area setName(String areaname) { name = areaname; return this; } public String getName() { return name; } }
City 類:
public class City extends Area { private Area adminArea; @Override public void displayName() { System.out.println(getName()); } public Area getAdminArea() { return adminArea; } @Override public Area setAdminArea(Area area) { this.adminArea = area; return this; } }
AdminArea 類:
public class AdminArea extends Area { public AdminArea(String areaname) { super(); setName(areaname); } @Override public void displayName() { System.out.println(getName()); } @Override public Area setAdminArea(Area area) { return null; } @Override public Area getAdminArea() { return null; } }
AdminAreaFactory 工廠類:
public class AdminAreaFactory { private static Hashtable hashtable = new Hashtable(); public static Area produce(String name){ if(null==name){ return null; } Area area = (Area) hashtable.get(name); if(null==area){ area = new AdminArea(name); hashtable.put(name,area); } return area; } public static int getObjectCount(){ return hashtable.size(); } }
測試類:
public class WorkClass { public void test() { Area city0 = new City().setName("hangzhou") .setAdminArea(AdminAreaFactory.produce("zhejiang")); Area city1 = new City().setName("suzhou") .setAdminArea(AdminAreaFactory.produce("jiangsu")); Area city2 = new City().setName("huzhou") .setAdminArea(AdminAreaFactory.produce("zhejiang")); Area city3 = new City().setName("nanjing") .setAdminArea(AdminAreaFactory.produce("jiangsu")); Area city4 = new City().setName("ninbo") .setAdminArea(AdminAreaFactory.produce("zhejiang")); List<Area> list = new ArrayList<Area>(); list.add (city0); list.add (city1); list.add (city2); list.add (city3); list.add (city4); for (int i = 0; i < list.size(); i++) { Area city = list.get(i); city.getAdminArea().displayName(); city.displayName(); } System.out.println(String.format("AdminAreaFactory.getObjectCount()=%s", AdminAreaFactory.getObjectCount())); } }
測試結果輸出:
06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: zhejiang 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: hangzhou 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: jiangsu 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: suzhou 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: zhejiang 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: huzhou 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: jiangsu 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: nanjing 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: zhejiang 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: ninbo 06-21 11:57:12.637 30394-30394/com.example.qinghua_liu.myapplication I/System.out: AdminAreaFactory.getObjectCount()=2
通過AdminAreaFactory的管理,實現了AdminArea的共享,不需要每一次都重新創建對象,節省了系統開銷。