android-設(shè)計(jì)模式--單例模式在項(xiàng)目中的應(yīng)用

目的

android框架搭建的時(shí)候設(shè)計(jì)模式會(huì)起到很大的作用,在搭建初期的項(xiàng)目框架時(shí)飒赃,合理利用設(shè)計(jì)模式的一些理念和技巧,能讓你在構(gòu)建整個(gè)項(xiàng)目框架的時(shí)候更加游刃有余.學(xué)習(xí)設(shè)計(jì)模式的初衷不僅僅是能讓你的代碼結(jié)構(gòu)更加整潔易讀科侈,而且能降低各模塊之間的耦合性载佳,使你的框架有更好的可拓展性,這樣在后期的需求不斷變動(dòng)的時(shí)候臀栈,就不必對(duì)整個(gè)代碼結(jié)構(gòu)和框架做大的改動(dòng)蔫慧,當(dāng)然,隨著后期業(yè)務(wù)的增多权薯,相應(yīng)的代碼重構(gòu)還是要有姑躲,在此設(shè)計(jì)模式的學(xué)習(xí)及框架的搭建只是為了減少后期大幅度重構(gòu)代碼的工作,畢竟盟蚣,程序員黍析,都是懶人.

網(wǎng)上有很多關(guān)于設(shè)計(jì)模式的介紹,但是對(duì)于設(shè)計(jì)模式在項(xiàng)目中的運(yùn)用比較少屎开,尤其是對(duì)android項(xiàng)目的運(yùn)用阐枣,這次,我打算從頭梳理一遍設(shè)計(jì)模式奄抽,在梳理過(guò)程中蔼两,盡量貼合實(shí)際應(yīng)用需要,在項(xiàng)目中去闡述設(shè)計(jì)模式在各個(gè)地方和模塊的使用和技巧逞度,也算是重新學(xué)習(xí)一遍吧.

單例模式的定義

首先關(guān)于單例模式额划,定義相當(dāng)簡(jiǎn)單,單例模式即指創(chuàng)建單一的實(shí)例對(duì)象档泽,作為全局變量在各處引用.單例的意義在于俊戳,節(jié)省部分內(nèi)存開(kāi)支彬祖,相信在android開(kāi)發(fā)過(guò)程中大家都遇到過(guò)內(nèi)存溢出和泄露的問(wèn)題.使用單例模式就不得不說(shuō)一下內(nèi)存泄露和內(nèi)存溢出的問(wèn)題了.

關(guān)于內(nèi)存泄露與垃圾回收

所謂的內(nèi)存泄露是指什么呢?我們都知道品抽,java虛擬機(jī)中內(nèi)存是分為兩塊的(靜態(tài)的內(nèi)存不在這次考慮范圍內(nèi)储笑,只說(shuō)明問(wèn)題,后續(xù)可以討論java內(nèi)存構(gòu)成問(wèn)題)即堆內(nèi)存和棧內(nèi)存圆恤,堆內(nèi)存和棧內(nèi)存都為動(dòng)態(tài)分配地址突倍。我們通常所定義的變量,分為基本數(shù)據(jù)類型和引用變量盆昙,基本數(shù)據(jù)類型包括int羽历、long、double淡喜、boolean秕磷、double等常用的基本變量,這些包括他們的封包變量即Integer炼团、Double澎嚣、Boolean等在聲明及賦值時(shí),java會(huì)直接從棧內(nèi)直接分配內(nèi)存瘟芝,而像自定義的實(shí)體易桃,在聲明及通過(guò)關(guān)鍵子new來(lái)創(chuàng)建實(shí)例時(shí),會(huì)在內(nèi)存中分配兩個(gè)地址锌俱,棧內(nèi)會(huì)分配給引用變量一個(gè)地址作為聲明及指針存放的空間(指針概念請(qǐng)了解C/C++相關(guān)鏈表指針概念)晤郑,然后指針指向的位置即為通過(guò)關(guān)鍵字new 創(chuàng)建實(shí)例的具體數(shù)據(jù)在堆內(nèi)存的位置。再回到內(nèi)存泄露和內(nèi)存溢出的問(wèn)題上來(lái)講贸宏,內(nèi)存泄露即指在java虛擬機(jī)分配給你定義的變量?jī)?nèi)存后造寝,無(wú)法釋放你申請(qǐng)的這個(gè)內(nèi)存,簡(jiǎn)單來(lái)講就是吭练,你在創(chuàng)建引用變量的時(shí)候诫龙,并沒(méi)有在使用完成后釋放這個(gè)內(nèi)存,當(dāng)然你可能說(shuō)java 的gc回收機(jī)制會(huì)幫你完成线脚,但是赐稽,無(wú)疑這樣效率就會(huì)極端低下.單個(gè)內(nèi)存泄露可能效果不明顯,但是大量的內(nèi)存泄露就會(huì)導(dǎo)致內(nèi)存損耗嚴(yán)重浑侥,另外姊舵,gc垃圾回收時(shí)會(huì)阻塞主線程,這就造成了UI卡頓寓落,這也是一部分UI卡頓的原因.(具體java gc回收機(jī)制相對(duì)比較復(fù)雜括丁,在此我們不做更深入的了解,只做說(shuō)明伶选,如果想更深入了解java gc機(jī)制及過(guò)程建議查詢相關(guān)資料).至于內(nèi)存溢出史飞,相對(duì)而言更好理解尖昏,即指申請(qǐng)內(nèi)存的時(shí)候,系統(tǒng)分配的內(nèi)存不足就會(huì)引起內(nèi)存溢出.這種溢出從某種程度上講构资,也有一部分內(nèi)存泄露導(dǎo)致內(nèi)存不足的原因.所以抽诉,總結(jié)而言就是,過(guò)度的創(chuàng)建對(duì)象吐绵,定義不必要的變量會(huì)導(dǎo)致內(nèi)存消耗增加迹淌,大量的內(nèi)存資源被浪費(fèi),引起內(nèi)存泄露.而這也正是我們?yōu)槭裁匆脝卫J絹?lái)處理一些全局的變量和工具類的意義.當(dāng)然己单,單例模式只是從一定程度上避免內(nèi)存的問(wèn)題唉窃,并不是能從根本上解決問(wèn)題之道.

好了,扯了這么多終于又回歸到咱們的單例模式這個(gè)設(shè)計(jì)理念上纹笼,設(shè)計(jì)模式作為一個(gè)最經(jīng)典的設(shè)計(jì)模式.被大量的研究和探討.相繼也出現(xiàn)了各種版本纹份,在此就對(duì)各個(gè)版本做一下簡(jiǎn)單介紹.

經(jīng)典模式的單例(懶漢模式)

public class  Singleton {
private static Singleton singleton = null;
private  Singleton() {
}
public static Singleton getInstance() {
if(null==singleton) {
singleton =  new  Singleton();
}
return   singleton;
}
}

經(jīng)典模式會(huì)將構(gòu)造器私有,防止外部通過(guò)new關(guān)鍵字穿件對(duì)象實(shí)體廷痘,對(duì)外提供靜態(tài)方法getInstantce來(lái)獲取單一實(shí)例蔓涧,調(diào)用方法時(shí)做非空判斷保證在調(diào)用時(shí)至少已經(jīng)創(chuàng)建出對(duì)象.

當(dāng)然,眾所周知的這種方式是有弊端的牍疏,弊端就在于多線程無(wú)法保證單例模式的唯一性蠢笋。

關(guān)于線程的cpu調(diào)度

在這里我們不得不提一下線程的本質(zhì),大家都知道線程是cpu調(diào)度的基本單位鳞陨,為什么這么說(shuō)呢,很簡(jiǎn)單瞻惋,線程的本質(zhì)就是cpu會(huì)分配一個(gè)最小執(zhí)行片段時(shí)間厦滤,采用輪詢的方式去不停的執(zhí)行線程,分配資源歼狼,從某種程度上來(lái)講掏导,單核cpu本質(zhì)上應(yīng)該是沒(méi)有真正并發(fā)執(zhí)行的過(guò)程,單核cpu只是通過(guò)將線程執(zhí)行時(shí)間碎片化羽峰,輪詢執(zhí)行調(diào)度趟咆,從用戶的角度來(lái)講,看上去是同時(shí)執(zhí)行的兩個(gè)線程其實(shí)都是有先后的梅屉。當(dāng)然多核cpu就會(huì)有真正的并發(fā)了.不過(guò)這些和我們說(shuō)的經(jīng)典單例的弊端并沒(méi)有啥米關(guān)系值纱,經(jīng)典單例的問(wèn)題在于數(shù)據(jù)同步.即兩個(gè)線程都經(jīng)過(guò)if判斷之后進(jìn)入方法體時(shí)依次執(zhí)行,這樣就會(huì)創(chuàng)建多次對(duì)象坯汤,即不能保證單例的唯一性.具體請(qǐng)參考下圖

example.png

改進(jìn)地方法想必大家都是到的虐唠,最簡(jiǎn)單的方式就是添加synchronized同步鎖(關(guān)于互斥鎖等線程同步相關(guān)我們后續(xù)再討論).而這也必將導(dǎo)致的一個(gè)問(wèn)題就是,效率的低下惰聂,一般來(lái)講疆偿,我們作為單例的變量很少涉及線程問(wèn)題咱筛,當(dāng)然秉持著嚴(yán)謹(jǐn)?shù)膽B(tài)度我們依然還是需要保證在多線程的情況下的問(wèn)題,這樣的話杆故,我們只能繼續(xù)修改單例的寫(xiě)法迅箩,以保證我們的需求.這樣我們就不得不介紹另一種單例模式,惡漢模式.
所謂惡漢模式处铛,即初始化的時(shí)候就已經(jīng)創(chuàng)建對(duì)象沙热,這樣就不需要坐非空判斷,則也不會(huì)出現(xiàn)線程同步問(wèn)題了.具體代碼如下.

惡漢模式

public class Singleton {
private static Singleton  singleton = new   Singleton();
private  Singleton() {
}
public static  Singleton  getInstance() {
return  singleton;
}
}

當(dāng)然罢缸,單例的其他寫(xiě)法網(wǎng)上也有也行篙贸,筆者個(gè)人認(rèn)為這三種方法較為常用,剩余其他的寫(xiě)法筆者未做深入研究,開(kāi)發(fā)過(guò)程中也比較少見(jiàn)枫疆,故此也不再討論.

項(xiàng)目中應(yīng)用

開(kāi)篇說(shuō)要將單例的設(shè)計(jì)模式運(yùn)用在框架搭建中爵川,筆者寫(xiě)了一段關(guān)于單例應(yīng)用于用戶管理工具的代碼,希望大家一塊學(xué)習(xí)息楔,有不足的地方希望大家批評(píng)指正.
附上筆者代碼:

packagecom.ss.single;
import java.io.Serializable;
import java.util.Map;
/**
* Created by Administrator on 2016/11/23.
* 用戶實(shí)體類
*/
public class User implements Serializable {
//用戶姓名
private String userName;
//用戶昵稱
private String nickName;
//用戶密碼
private String pwd;
//用戶權(quán)限
private String permission;
//用戶相關(guān)資料鍵值對(duì)
private Map<String,String> datas;
public void  setUserName(String userName) {
this.userName= userName;
}
public void  setNickName(String nickName) {
this.nickName= nickName;
}
public void  setPwd(String pwd) {
this.pwd= pwd;
}
public void  setPermission(String permission) {
this.permission= permission;
}
public void  setDatas(Map datas) {
this.datas= datas;
}
public  String  getUserName() {
return userName;
}
public  String  getNickName() {
return  nickName;
}
public String getPwd() {
return pwd;
}
public String  getPermission() {
return permission;
}
public  Map  getDatas() {
return datas;
}
@Override
public String  toString() {
return"User{"+
"userName='"+userName+'\''+
", nickName='"+nickName+'\''+
", pwd='"+pwd+'\''+
", permission='"+permission+'\''+
", datas="+datas+
'}';
}
}

用戶管理工具類.

packagecom.ss.single;
importandroid.support.annotation.NonNull;
/**
* Created by Administrator on 2016/11/23.
*/
public class  UserHelper {
private static   UserHelperhelper = new  UserHelper();
private  User  user;
private  UserHelper() {
}
/**
* 獲取當(dāng)前userhelper實(shí)例
*
*@return
*/
public static  UserHelper  getInstance() {
return  helper;
}
/**
* 獲取當(dāng)前用戶
*
*@return
*/
public  User    getCurrentUser() {
return   user;
}
/**
* 替換/初始化當(dāng)前用戶
*
*@param  user
*/
public void   replaceUser(User user) {
this.user= user;
}
/**
* 退出當(dāng)前登錄
*/
public void  logout() {
user=null;
}
/**
* 判斷本地登錄是否成功
*
*@param  userName
*@param  pwd
*@return
*/
public boolean   localLogin(@NonNull  String userName,@NonNull  String pwd) {
if(null!=user? userName.equals(user.getUserName()) && pwd.equals(user.getPwd()) :false)
return true;
return false;
}
}

參考書(shū)籍:HeadFirst設(shè)計(jì)模式.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末寝贡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子值依,更是在濱河造成了極大的恐慌圃泡,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愿险,死亡現(xiàn)場(chǎng)離奇詭異颇蜡,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)辆亏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)风秤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人扮叨,你說(shuō)我怎么就攤上這事缤弦。” “怎么了彻磁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵碍沐,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我衷蜓,道長(zhǎng)累提,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任恍箭,我火速辦了婚禮刻恭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己鳍贾,他們只是感情好鞍匾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著骑科,像睡著了一般橡淑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上咆爽,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天梁棠,我揣著相機(jī)與錄音,去河邊找鬼斗埂。 笑死符糊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的呛凶。 我是一名探鬼主播男娄,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼漾稀!你這毒婦竟也來(lái)了模闲?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤崭捍,失蹤者是張志新(化名)和其女友劉穎尸折,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體殷蛇,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡实夹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晾咪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片收擦。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖谍倦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情泪勒,我是刑警寧澤昼蛀,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站圆存,受9級(jí)特大地震影響叼旋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜沦辙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一夫植、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦详民、人聲如沸延欠。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)由捎。三九已至,卻和暖如春饿凛,著一層夾襖步出監(jiān)牢的瞬間狞玛,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工涧窒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留心肪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓纠吴,卻偏偏與公主長(zhǎng)得像硬鞍,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子呜象,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,116評(píng)論 25 707
  • 從三月份找實(shí)習(xí)到現(xiàn)在膳凝,面了一些公司,掛了不少恭陡,但最終還是拿到小米蹬音、百度、阿里休玩、京東著淆、新浪、CVTE拴疤、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,246評(píng)論 11 349
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法永部,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法呐矾,繼承相關(guān)的語(yǔ)法苔埋,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,631評(píng)論 18 399
  • 推薦有效期:170711013-170712084【1】任三13 16 19 16 17 18 08 09 1...
    觀瀾看彩閱讀 441評(píng)論 1 2
  • 近兩年以來(lái)工作到了“瓶頸期”蜒犯,工作枯燥乏味组橄,沒(méi)有挑戰(zhàn)性,也有想過(guò)既然沒(méi)有其他事情可做那就把手邊的工作干到極致罚随,可這...
    木易一丹閱讀 199評(píng)論 0 0