編輯:關於android開發
享元模式是結構型設計模式之一,是對對象池的一種實現。就像它的名字一樣,共享對象,避免重復的創建。我們常用的
String
就是使用了共享模式,所以String
類型的對象創建後就不可改變,如果當兩個String
對象所包含的內容相同時,JVM只創建一個String
對象對應這兩個不同的對象引用。
采用一個共享來避免大量擁有相同內容對象的開銷。使用享元模式可有效支持大量的細粒度對象。
(1)系統中存在大量的相似對象。
(2)細粒度的對象都具備較接近的外部狀態,而且內部狀態與環境不關,也就是說對象沒有特定身份。
(3)需要緩沖池的場景。
PS:內部狀態與外部狀態:在享元對象內部並且不會隨著環境改變而改變的共享部分,可以稱之為享元對象的內部狀態,反之隨著環境改變而改變的,不可共享的狀態稱之為外部狀態。
享元模式分為單純享元模式和復合享元模式,上圖是復合享元模式。
(1)Flyweight
:享元對象抽象基類或者接口。
(2)ConcreateFlyweight
:具體的享元對象,如果有內部狀態的話,必須負責為內部狀態提供存儲空間。
(3)UnsharadConcreateFlyweight
:復合享元角色所代表的對象是不可以共享的,並且可以分解成為多個單純享元對象的組合。單純享元模式沒有此項,這也是兩者在結構上的區別。
(4)FlyweightFactoiy
:享元工廠,負責管理享元對象池和創建享元對象。
(5)Client
:維護對所有享元對象的引用,而且還需要存儲對應的外蘊狀態。
情景:過年買火車票的時候,我們需要查詢車票的情況,那麼如果每次查詢車票時都創建一個結果,那麼必然會大量的創建出許多重復的對象,頻繁的去銷毀他們,使得GC任務繁重。那麼這時我們可以使用享元模式,將這些對象緩存起來,查詢時優先使用緩存,沒有緩存在重新創建。
首先是Ticket接口(Flyweight):
public interface Ticket {
public void showTicketInfo(String bunk);
}
TrainTicket具體實現類(ConcreateFlyweight):
//火車票
public class TrainTicket implements Ticket{
public String from; // 始發地
public String to; // 目的地
public String bunk; //鋪位
public int price; //價格
public TrainTicket(String from, String to) {
this.from = from;
this.to = to;
}
@Override
public void showTicketInfo(String bunk) {
price = new Random().nextInt(300);
System.out.println("購買 從 " + from + " 到 " + to + "的" + bunk + "火車票" + ", 價格:" + price);
}
}
TicketFactory 管理查詢火車票(FlyweightFactoiy):
public class TicketFactory {
static Map sTicketMap = new ConcurrentHashMap();
public static Ticket getTicket(String from ,String to){
String key = from + "-" + to;
if(sTicketMap.containsKey(key)){
System.out.println("使用緩存 ==> " + key);
return sTicketMap.get(key);
}else{
System.out.println("創建對象 ==> " + key);
Ticket ticket = new TrainTicket(from, to);
sTicketMap.put(key, ticket);
return ticket;
}
}
}
查詢:
final class Client {
public static void main(String[] args) {
Ticket ticket01 = TicketFactory.getTicket("北京", "青島");
ticket01.showTicketInfo("上鋪");
Ticket ticket02 = TicketFactory.getTicket("北京", "青島");
ticket02.showTicketInfo("下鋪");
Ticket ticket03 = TicketFactory.getTicket("北京", "西安");
ticket03.showTicketInfo("坐票");
}
}
結果
創建對象 ==> 北京-青島
購買 從 北京 到 青島的上鋪火車票, 價格:71
使用緩存 ==> 北京-青島
購買 從 北京 到 青島的下鋪火車票, 價格:32
創建對象 ==> 北京-西安
購買 從 北京 到 西安的坐票火車票, 價格:246
因為Android是事件驅動的,因此如果通過new創建
Message
就會創建大量的Message
對象,導致內存占用率高,頻繁GC等問題。那麼Message
就采用了享元模式。
Message
通過next
成員變量保有對下一個Message
的引用,最後一個可用Message
的next
則為空。從而構成了一個Message鏈表。Message Pool
就通過該鏈表的表頭管理著所有閒置的Message
,一個Message
在使用完後可以通過recycle()
方法進入Message Pool
,並在需要時通過obtain
靜態方法從Message Pool
獲取。Message
承擔了享元模式中3個元素的職責,即是Flyweight
抽象,又是ConcreateFlyweight
角色,同時又承擔了FlyweightFactoiy
管理對象池的職責。
所以使用Message推薦obtain(),不要去new了。
//1。使用new Message()
//Message mess = new Message();
//2。使用Message.obtain()
Message mess = Message.obtain();
mess.what = 1;
//Message mess = mHandler.obtainMessage(1); 與上兩行的代碼一樣,可以參考源碼查看
mHandler.sendMessage(mess);
(1)大大減少應用程序創建的對象,降低程序內存的占用,增強程序的性能。
(2)使用享元模式,可以讓享元對象可以在不同的環境中被共享。
(1)使得系統更加復雜。為了使對象可以共享,需要將一些狀態外部化,這使得程序的邏輯復雜化。
(2)享元模式將需、享元對象的狀態外部化,而讀取外部狀態使得運行時間稍微變長。
在eclipse中安裝上genymotion插件,eclipsegenymotion1.安裝genymotion-vbox,選擇安裝目錄。 具體安裝過程可見http://
Android listview和ListAdapter搭配使用,androidlistadapterListView時Android中自帶的數據顯示控件,要使用List
Android中Canvas繪圖基礎詳解(附源碼下載) Android中,如果我們想繪制復雜的自定義View或游戲,我們就需要熟悉繪圖API。Android通過Canva
Android--JNI簡單的實例解析 最近項目迭代了幾個版本,目前比較輕松,雖然項目閒了,但是人不能太閒,否則就廢了。千裡之行始於足下、量變引起質變、學而不思則罔.