標籤:設計模式 單例模式 java android
1.設計模式執行個體-單例模式
單例模式,故名思議,是指在一個類中通過設定靜態使得其僅創造一個唯一的執行個體。這樣設定的目的是滿足開發人員的希望——這個類只需要被執行個體化建立一次,同時因為其為靜態緣故,載入的速度也應該快於正常執行個體化一個類的速度(理論上)。
在Android開發中,當我們需要建立一個Fragment的時候常常會用到這樣的模式,沒有代碼的學習是虛無的,接下來亮代碼學習:
public class SelectFrame extends Fragment { private final static String selectFrameKey = "SFKey"; private static SelectFrame mSelectFrame; private ArrayList<String> frameList; public static SelectFrame getInstance(ArrayList<String> frameList){ if (mSelectFrame == null) { mSelectFrame = new SelectFrame(); } Bundle bundle = new Bundle(); bundle.putStringArrayList(selectFrameKey, frameList); mSelectFrame.setArguments(bundle); return mSelectFrame; }
......
這是我在一個Fragment類裡面定義的其中一部分,首先必須要定義一個自身的靜態mSelectFrame。然後通過一個靜態方法 getInstance()來執行個體化這個mSelectFrame,很明顯,這裡通過判斷其是否為空白的方式,使得每一次我們使用getInstance的時候都返回的是同一個對象mSelectFrame。
getInstance方法中有時我們也會放入一些我們需要傳遞的參數,比如我這個方法中放入了一個List對象,然後直接在裡面用Bundle裝載這個List對象,原本我們可能是在外部來做這些操作的,然而現在卻直接通過這個方法將資料傳入的操作整合到了這個Fragment中,即減少了外部Activity的邏輯代碼,也使得這個Fragment在複用的時候操作更方便。(再通過setArguments的方法儲存資料)。
接下來看我們的onCreateView方法:
@Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { view = inflater.inflate(R.layout.select_frame_fragment, container, false); Bundle bundle = mSelectFrame.getArguments(); frameList = bundle.getStringArrayList(selectFrameKey);} 這裡我們就將從前面getInstance中setArguments儲存下來的資料通過Fragment的getArguments方法重新將資料讀取出來。這樣就完成了我們的目的。
接下來就是在Activity中建立我們這個Fragment對象了:
selectFrameFrag = SelectFrame.getInstance(nameFrameThumbnail); fm.beginTransaction().add(R.id.fragment_frame_container, selectFrameFrag).commit();
(fm是FragmentManager..)
這樣就OK了。
2.單例模式的分類
單例模式有兩種建立方式,分別為餓漢式和懶漢式。
餓漢式,故名思議,很餓,在一開始就直接建立了這個對象。
懶漢式,顧名思義,很懶,只有在你要調用它的時候,通過自己寫的方法裡面來對他執行個體化。剛剛上面那個例子就是懶漢式的。
也許這麼說你會有一點不明白(其實應該沒有人不明白吧= =),然後其實只要看代碼的這個地方:
private static SelectFrame mSelectFrame;
上面這個代碼,這裡一開始定義自身的靜態時,沒有執行個體化它,那麼就是個懶漢.然後只有在我調用getInstance方法的時候,才在裡面對他進行執行個體化(new SelectFrame()).
然後我們再看看餓漢:
private static SelectFrame mSelectFrame = new SelectFrame();
在定義的時候就已經執行個體化了.
3.單例模式的安全執行緒問題
沒錯,單例模式畢竟就是像上面講的這麼簡單。但需要注意的是,單例模式中的餓漢式是安全執行緒的,而懶漢式是線程不安全的,我們一般會再懶漢式的getInstance方法中通過synchronized上鎖。類似於這樣:
if (mSelectFrame == null) { synchronized (SelectFrame.class) { if (mSelectFrame == null) { mSelectFrame = new SelectFrame(); } } }
有人說為什麼要用兩個if XX == null。這裡是因為提高效率,只有一個也是可以的,但效率上大大減低,因為不是每一次調用的時候我們要判斷他是否同步,應該是如果判斷當前為null的話,我們就直接不讓他進入了,不需要判斷是否同步。只有滿足第一個條件的時候,我們才需要用鎖來判斷它是否安全執行緒。(這裡的意思也是說明if一條語句的判斷速度當然比synchronized (SelectFrame.class)快。。)
另外,在我們使用單例模式的時候,有些人會去私人化這個類的構造方法,使得這個類只能通過自己寫的getInstance()來建立。類似於這樣:
private SelectFrame() { // 並不需要做什麼,只需要將這個外面的public改成private就好了=。= }
嗯嗯,這麼一來外部就只能按我要求的方法來建立這個對象了.
在這裡也基本將單例模式的使用基本講完了,接下來還會繼續寫其他的設計模式的使用,如果有涉及到Android上的都會儘力用Android上的例子來講,加深印象。
Make Life Get Better.
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
設計模式執行個體學習-單例模式(Android中的使用情境)