【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Kotlin中的單例模式有哪些_第1頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Kotlin中的單例模式有哪些_第2頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Kotlin中的單例模式有哪些_第3頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Kotlin中的單例模式有哪些_第4頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Kotlin中的單例模式有哪些_第5頁(yè)
已閱讀5頁(yè),還剩5頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Kotlin中的單例模式有哪些

這篇文章給大家介紹Kotlin中的單例模式有哪些,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。一、餓漢式實(shí)現(xiàn)//Java實(shí)現(xiàn)

public

class

SingletonDemo

{

private

static

SingletonDemo

instance=new

SingletonDemo();

private

SingletonDemo(){

}

public

static

SingletonDemo

getInstance(){

return

instance;

}

}

//Kotlin實(shí)現(xiàn)

object

SingletonDemo這里很多小伙伴,就吃了一驚。我靠一個(gè)object關(guān)鍵字就完成相同的功能?一行代碼?Kotlin的對(duì)象聲明學(xué)習(xí)了Kotlin的小伙伴肯定知道,在Kotlin中類沒(méi)有靜態(tài)方法。如果你需要寫一個(gè)可以無(wú)需用一個(gè)類的實(shí)例來(lái)調(diào)用,但需要訪問(wèn)類內(nèi)部的函數(shù)(例如,工廠方法,單例等),你可以把該類聲明為一個(gè)對(duì)象。該對(duì)象與其他語(yǔ)言的靜態(tài)成員是類似的。如果你想了解Kotlin對(duì)象聲明的更多內(nèi)容。請(qǐng)點(diǎn)擊---傳送門到這里,如果還是有很多小伙伴不是很相信一行代碼就能解決這個(gè)功能,我們可以通過(guò)一下方式查看Kotlin的字節(jié)碼。查看Kotlin對(duì)應(yīng)字節(jié)碼我們進(jìn)入我們的AndroidStudio(我的AndroidStudio3.0,如果你的編譯器版本過(guò)低,請(qǐng)自動(dòng)升級(jí))選擇Tools工具欄,選擇"Kotlin",選擇“ShowKotlinBytecode"選擇過(guò)后就會(huì)進(jìn)入到下方界面:點(diǎn)擊"Decompile"根據(jù)字節(jié)碼得到以下代碼public

final

class

SingletonDemo

{

public

static

final

SingletonDemo

INSTANCE;

private

SingletonDemo(){}

static

{

SingletonDemo

var0

=

new

SingletonDemo();

INSTANCE

=

var0;

}

}通過(guò)以上代碼,我們了解事實(shí)就是這個(gè)樣子的,使用Kotlin"object"進(jìn)行對(duì)象聲明與我們的餓漢式單例的代碼是相同的。二、懶漢式//Java實(shí)現(xiàn)

public

class

SingletonDemo

{

private

static

SingletonDemo

instance;

private

SingletonDemo(){}

public

static

SingletonDemo

getInstance(){

if(instance==null){

instance=new

SingletonDemo();

}

return

instance;

}

}

//Kotlin實(shí)現(xiàn)

class

SingletonDemo

private

constructor()

{

companion

object

{

private

var

instance:

SingletonDemo?

=

null

get()

{

if

(field

==

null)

{

field

=

SingletonDemo()

}

return

field

}

fun

get():

SingletonDemo{

//細(xì)心的小伙伴肯定發(fā)現(xiàn)了,這里不用getInstance作為為方法名,是因?yàn)樵诎樯鷮?duì)象聲明時(shí),內(nèi)部已有g(shù)etInstance方法,所以只能取其他名字

return

instance!!

}

}

}上述代碼中,我們可以發(fā)現(xiàn)在Kotlin實(shí)現(xiàn)中,我們讓其主構(gòu)造函數(shù)私有化并自定義了其屬性訪問(wèn)器,其余內(nèi)容大同小異。如果有小伙伴不清楚Kotlin構(gòu)造函數(shù)的使用方式。請(qǐng)點(diǎn)擊---構(gòu)造函數(shù)不清楚Kotlin的屬性與訪問(wèn)器,請(qǐng)點(diǎn)擊---屬性和字段三、線程安全的懶漢式//Java實(shí)現(xiàn)

public

class

SingletonDemo

{

private

static

SingletonDemo

instance;

private

SingletonDemo(){}

public

static

synchronized

SingletonDemo

getInstance(){//使用同步鎖

if(instance==null){

instance=new

SingletonDemo();

}

return

instance;

}

}

//Kotlin實(shí)現(xiàn)

class

SingletonDemo

private

constructor()

{

companion

object

{

private

var

instance:

SingletonDemo?

=

null

get()

{

if

(field

==

null)

{

field

=

SingletonDemo()

}

return

field

}

@Synchronized

fun

get():

SingletonDemo{

return

instance!!

}

}

}大家都知道在使用懶漢式會(huì)出現(xiàn)線程安全的問(wèn)題,需要使用使用同步鎖,在Kotlin中,如果你需要將方法聲明為同步,需要添加**@Synchronized**注解。四、雙重校驗(yàn)鎖式(DoubleCheck)//Java實(shí)現(xiàn)

public

class

SingletonDemo

{

private

volatile

static

SingletonDemo

instance;

private

SingletonDemo(){}

public

static

SingletonDemo

getInstance(){

if(instance==null){

synchronized

(SingletonDemo.class){

if(instance==null){

instance=new

SingletonDemo();

}

}

}

return

instance;

}

}

//kotlin實(shí)現(xiàn)

class

SingletonDemo

private

constructor()

{

companion

object

{

val

instance:

SingletonDemo

by

lazy(mode

=

LazyThreadSafetyMode.SYNCHRONIZED)

{

SingletonDemo()

}

}

}哇!小伙伴們驚喜不,感不感動(dòng)啊。我們居然幾行代碼就實(shí)現(xiàn)了多行的Java代碼。其中我們運(yùn)用到了Kotlin的延遲屬性Lazy。Lazy是接受一個(gè)lambda并返回一個(gè)Lazy實(shí)例的函數(shù),返回的實(shí)例可以作為實(shí)現(xiàn)延遲屬性的委托:第一次調(diào)用get()會(huì)執(zhí)行已傳遞給lazy()的lambda表達(dá)式并記錄結(jié)果,后續(xù)調(diào)用get()只是返回記錄的結(jié)果。這里還有有兩個(gè)額外的知識(shí)點(diǎn)。高階函數(shù),高階函數(shù)是將函數(shù)用作參數(shù)或返回值的函數(shù)(我很糾結(jié)我到底講不講,哎)。大家還是看這個(gè)高階函數(shù)委托屬性如果你了解以上知識(shí)點(diǎn),我們直接來(lái)看Lazy的內(nèi)部實(shí)現(xiàn)。Lazy內(nèi)部實(shí)現(xiàn)public

fun

<T>

lazy(mode:

LazyThreadSafetyMode,

initializer:

()

->

T):

Lazy<T>

=

when

(mode)

{

LazyThreadSafetyMode.SYNCHRONIZED

->

SynchronizedLazyImpl(initializer)

LazyThreadSafetyMode.PUBLICATION

->

SafePublicationLazyImpl(initializer)

LazyThreadSafetyMode.NONE

->

UnsafeLazyImpl(initializer)

}觀察上述代碼,因?yàn)槲覀儌魅氲膍ode=LazyThreadSafetyMode.SYNCHRONIZED,那么會(huì)直接走SynchronizedLazyImpl,我們繼續(xù)觀察SynchronizedLazyImpl。Lazy接口SynchronizedLazyImpl實(shí)現(xiàn)了Lazy接口,Lazy具體接口如下:public

interface

Lazy<out

T>

{

//當(dāng)前實(shí)例化對(duì)象,一旦實(shí)例化后,該對(duì)象不會(huì)再改變

public

val

value:

T

//返回true表示,已經(jīng)延遲實(shí)例化過(guò)了,false

表示,沒(méi)有被實(shí)例化,

//一旦方法返回true,該方法會(huì)一直返回true,且不會(huì)再繼續(xù)實(shí)例化

public

fun

isInitialized():

Boolean

}繼續(xù)查看SynchronizedLazyImpl,具體實(shí)現(xiàn)如下:SynchronizedLazyImpl內(nèi)部實(shí)現(xiàn)private

class

SynchronizedLazyImpl<out

T>(initializer:

()

->

T,

lock:

Any?

=

null)

:

Lazy<T>,

Serializable

{

private

var

initializer:

(()

->

T)?

=

initializer

@Volatile

private

var

_value:

Any?

=

UNINITIALIZED_VALUE

//

final

field

is

required

to

enable

safe

publication

of

constructed

instance

private

val

lock

=

lock

?:

this

override

val

value:

T

get()

{

val

_v1

=

_value

//判斷是否已經(jīng)初始化過(guò),如果初始化過(guò)直接返回,不在調(diào)用高級(jí)函數(shù)內(nèi)部邏輯

if

(_v1

!==

UNINITIALIZED_VALUE)

{

@Suppress("UNCHECKED_CAST")

return

_v1

as

T

}

return

synchronized(lock)

{

val

_v2

=

_value

if

(_v2

!==

UNINITIALIZED_VALUE)

{

@Suppress("UNCHECKED_CAST")

(_v2

as

T)

}

else

{

val

typedValue

=

initializer!!()//調(diào)用高級(jí)函數(shù)獲取其返回值

_value

=

typedValue

//將返回值賦值給_value,用于下次判斷時(shí),直接返回高級(jí)函數(shù)的返回值

initializer

=

null

typedValue

}

}

}

//省略部分代碼

}通過(guò)上述代碼,我們發(fā)現(xiàn)SynchronizedLazyImpl覆蓋了Lazy接口的value屬性,并且重新了其屬性訪問(wèn)器。其具體邏輯與Java的雙重檢驗(yàn)是類似的。到里這里其實(shí)大家還是肯定有疑問(wèn),我這里只是實(shí)例化了SynchronizedLazyImpl對(duì)象,并沒(méi)有進(jìn)行值的獲取,它是怎么拿到高階函數(shù)的返回值呢?。這里又涉及到了委托屬性。委托屬性語(yǔ)法是:val/var<屬性名>:<類型>by<表達(dá)式>。在by后面的表達(dá)式是該委托,因?yàn)閷傩詫?duì)應(yīng)的get()(和set())會(huì)被委托給它的getValue()和setValue()方法。屬性的委托不必實(shí)現(xiàn)任何的接口,但是需要提供一個(gè)getValue()函數(shù)(和setValue()——對(duì)于var屬性)。而Lazy.kt文件中,聲明了Lazy接口的getValue擴(kuò)展函數(shù)。故在最終賦值的時(shí)候會(huì)調(diào)用該方法。@ernal.InlineOnly

//返回初始化的值。

public

inline

operator

fun

<T>

Lazy<T>.getValue(thisRef:

Any?,

property:

KProperty<*>):

T

=

value五、靜態(tài)內(nèi)部類式//Java實(shí)現(xiàn)

public

class

SingletonDemo

{

private

static

class

SingletonHolder{

private

static

SingletonDemo

instance=new

SingletonDemo();

}

private

SingletonDemo(){

System.out.println("Singleton

has

loaded");

}

public

static

SingletonDemo

getInstance(){

return

SingletonHolder.instance;

}

}

//kotlin實(shí)現(xiàn)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論