Kotlin基礎(chǔ)(10)-代理模式在kotlin中的使用

前言

本文簡要介紹代理模式在kotlin中的使用

手寫一個(gè)代理模式

定義一個(gè)接口中定義行走方法,并在坦克類中實(shí)現(xiàn)行走方法字支,而行走的具體方法則由實(shí)現(xiàn)了行走方法的代理類實(shí)現(xiàn)轨香。代碼如下

interface Moveable {
    fun move();
}

class MoveProxy : Moveable {
    override fun move() {
        Log.e("move", "MoveProxy Moving")
    }

}

class Tank : Moveable {
    var proxy: MoveProxy;

    override fun move() {
            proxy.move()
    }

    constructor(proxy: MoveProxy) {
        this.proxy = proxy;
    }

}


       val tank:Tank= Tank(MoveProxy())
        tank.move()

測試結(jié)果

11-11 16:59:43.100 16068-16068/com.zhqy.javademo E/move: MoveProxy Moving

而我們也可以通過Kotlin中定義好的關(guān)鍵字by來實(shí)現(xiàn)上述功能

方法靜態(tài)代理的實(shí)現(xiàn)

interface Moveable {
    fun move();
}

class MoveProxy : Moveable {
    override fun move() {
        Log.e("move", "MoveProxy Moving")
    }

}

class Tank : Moveable by MoveProxy() {

}

測試結(jié)果

11-11 17:07:04.669 16274-16274/? E/move: MoveProxy Moving

從測試結(jié)果上來我們獲得了一樣的結(jié)果租漂,這是為什么呢

public final class Tank implements Moveable {
   // $FF: synthetic field
   private final MoveProxy $$delegate_0 = new MoveProxy();

   public void move() {
      this.$$delegate_0.move();
   }
}

從Java字節(jié)碼中可以看了只要通過關(guān)鍵字By聲明我們實(shí)例化的一個(gè)代理類理盆,余下的工作都由kotlin來為我們實(shí)現(xiàn)。kotlin不僅僅能實(shí)現(xiàn)方法的靜態(tài)代理也能夠?qū)崿F(xiàn)屬性的靜態(tài)代理

屬性靜態(tài)代理的實(shí)現(xiàn)

下面一個(gè)例子實(shí)現(xiàn)對屬性name的獲取數(shù)據(jù)和設(shè)置數(shù)據(jù)時(shí)打印相關(guān)的數(shù)據(jù)

class Person(){
    var name:String by MyDelegate()
}
//代理類
class MyDelegate{
    //獲取屬性值的方法
    /**
     * person 實(shí)例對象
     * property 屬性集合(包含修飾符倾剿,名稱等)
     */
    operator fun getValue(person: Person, property: KProperty<*>): String {

       Log.e("getValue","$person:${property.name}")
        return ""
    }

    /**
     * person 實(shí)例對象
     * property 屬性集合(包含修飾符筷频,名稱等)
     * s:設(shè)置的值
     */
    //設(shè)置屬性值的方法
    operator fun setValue(person: Person, property: KProperty<*>, s: String) {
        Log.e("getValue","$person:${property.name}:$s")
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }


}

        var person=Person();
        person.name="張三"
        person.name

測是結(jié)果

11-11 17:23:24.271 17635-17635/? E/setValue: com.zhqy.javademo.Person@3157fe3:name:張三
11-11 17:23:24.271 17635-17635/? E/getValue: com.zhqy.javademo.Person@3157fe3:name

需要注意的是代理類需要實(shí)現(xiàn)以下兩個(gè)方法

/**
     * person 實(shí)例對象
     * property 屬性集合(包含修飾符,名稱等)
     */
    operator fun getValue(person: Person, property: KProperty<*>): String {

       Log.e("getValue","$person:${property.name}")
        return ""
    }

    /**
     * person 實(shí)例對象
     * property 屬性集合(包含修飾符前痘,名稱等)
     * s:設(shè)置的值
     */
    //設(shè)置屬性值的方法
    operator fun setValue(person: Person, property: KProperty<*>, s: String) {
        Log.e("setValue","$person:${property.name}:$s")
    }

Java字節(jié)碼如下

public final class Person {
   // $FF: synthetic field
   static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.mutableProperty1(new MutablePropertyReference1Impl(Reflection.getOrCreateKotlinClass(Person.class), "name", "getName()Ljava/lang/String;"))};
   @NotNull
   private final MyDelegate name$delegate = new MyDelegate();

   @NotNull
   public final String getName() {
      return this.name$delegate.getValue(this, $$delegatedProperties[0]);
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      this.name$delegate.setValue(this, $$delegatedProperties[0], var1);
   }
}

從字節(jié)碼中可以看到聲明了代理類MyDelegate的一個(gè)對象凛捏,并在get和set方法中分別調(diào)用了getVale和setValue方法實(shí)現(xiàn)代理功能。
當(dāng)然也可以使用關(guān)鍵字

class Person(){
    var name:String by Delegate()
}

class Delegate(){
    
    operator  fun provideDelegate(person: Person, property: KProperty<*>):MyDelegate{
           return MyDelegate()
    }
}


//代理類
class MyDelegate{
    //獲取屬性值的方法
    /**
     * person 實(shí)例對象
     * property 屬性集合(包含修飾符芹缔,名稱等)
     */
    operator fun getValue(person: Person, property: KProperty<*>): String {

       Log.e("getValue","$person:${property.name}")
        return ""
    }

    /**
     * person 實(shí)例對象
     * property 屬性集合(包含修飾符坯癣,名稱等)
     * s:設(shè)置的值
     */
    //設(shè)置屬性值的方法
    operator fun setValue(person: Person, property: KProperty<*>, s: String) {
        Log.e("setValue","$person:${property.name}:$s")
    }


}

字節(jié)碼如下

// Person.java
package com.zhqy.javademo;

import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import kotlin.jvm.internal.MutablePropertyReference1Impl;
import kotlin.jvm.internal.Reflection;
import kotlin.reflect.KProperty;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = {1, 1, 10},
   bv = {1, 0, 2},
   k = 1,
   d1 = {"\u0000\u0014\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0002\b\b\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002R+\u0010\u0005\u001a\u00020\u00042\u0006\u0010\u0003\u001a\u00020\u00048F@FX\u0086\u008e\u0002¢\u0006\u0012\n\u0004\b\n\u0010\u000b\u001a\u0004\b\u0006\u0010\u0007\"\u0004\b\b\u0010\t¨\u0006\f"},
   d2 = {"Lcom/zhqy/javademo/Person;", "", "()V", "<set-?>", "", "name", "getName", "()Ljava/lang/String;", "setName", "(Ljava/lang/String;)V", "name$delegate", "Lcom/zhqy/javademo/MyDelegate;", "production sources for module app"}
)
public final class Person {
   // $FF: synthetic field
   static final KProperty[] $$delegatedProperties = new KProperty[]{(KProperty)Reflection.mutableProperty1(new MutablePropertyReference1Impl(Reflection.getOrCreateKotlinClass(Person.class), "name", "getName()Ljava/lang/String;"))};
   @NotNull
   private final MyDelegate name$delegate;

   @NotNull
   public final String getName() {
      return this.name$delegate.getValue(this, $$delegatedProperties[0]);
   }

   public final void setName(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
      this.name$delegate.setValue(this, $$delegatedProperties[0], var1);
   }

   public Person() {
      this.name$delegate = (new Delegate()).provideDelegate(this, $$delegatedProperties[0]);
   }
}
// Delegate.java
package com.zhqy.javademo;

import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import kotlin.reflect.KProperty;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = {1, 1, 10},
   bv = {1, 0, 2},
   k = 1,
   d1 = {"\u0000\u001e\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u001d\u0010\u0003\u001a\u00020\u00042\u0006\u0010\u0005\u001a\u00020\u00062\n\u0010\u0007\u001a\u0006\u0012\u0002\b\u00030\bH\u0086\u0002¨\u0006\t"},
   d2 = {"Lcom/zhqy/javademo/Delegate;", "", "()V", "provideDelegate", "Lcom/zhqy/javademo/MyDelegate;", "person", "Lcom/zhqy/javademo/Person;", "property", "Lkotlin/reflect/KProperty;", "production sources for module app"}
)
public final class Delegate {
   @NotNull
   public final MyDelegate provideDelegate(@NotNull Person person, @NotNull KProperty property) {
      Intrinsics.checkParameterIsNotNull(person, "person");
      Intrinsics.checkParameterIsNotNull(property, "property");
      return new MyDelegate();
   }
}
// MyDelegate.java
package com.zhqy.javademo;

import android.util.Log;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import kotlin.reflect.KProperty;
import org.jetbrains.annotations.NotNull;

@Metadata(
   mv = {1, 1, 10},
   bv = {1, 0, 2},
   k = 1,
   d1 = {"\u0000&\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000e\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0010\u0002\n\u0002\b\u0002\u0018\u00002\u00020\u0001B\u0005¢\u0006\u0002\u0010\u0002J\u001d\u0010\u0003\u001a\u00020\u00042\u0006\u0010\u0005\u001a\u00020\u00062\n\u0010\u0007\u001a\u0006\u0012\u0002\b\u00030\bH\u0086\u0002J%\u0010\t\u001a\u00020\n2\u0006\u0010\u0005\u001a\u00020\u00062\n\u0010\u0007\u001a\u0006\u0012\u0002\b\u00030\b2\u0006\u0010\u000b\u001a\u00020\u0004H\u0086\u0002¨\u0006\f"},
   d2 = {"Lcom/zhqy/javademo/MyDelegate;", "", "()V", "getValue", "", "person", "Lcom/zhqy/javademo/Person;", "property", "Lkotlin/reflect/KProperty;", "setValue", "", "s", "production sources for module app"}
)
public final class MyDelegate {
   @NotNull
   public final String getValue(@NotNull Person person, @NotNull KProperty property) {
      Intrinsics.checkParameterIsNotNull(person, "person");
      Intrinsics.checkParameterIsNotNull(property, "property");
      Log.e("getValue", "" + person + ':' + property.getName());
      return "";
   }

   public final void setValue(@NotNull Person person, @NotNull KProperty property, @NotNull String s) {
      Intrinsics.checkParameterIsNotNull(person, "person");
      Intrinsics.checkParameterIsNotNull(property, "property");
      Intrinsics.checkParameterIsNotNull(s, "s");
      Log.e("setValue", "" + person + ':' + property.getName() + ':' + s);
   }
}

感覺就是從創(chuàng)建一個(gè)實(shí)例變成了通過provideDelegate獲取代理類對象

標(biāo)準(zhǔn)庫中的代理模式

除了自己實(shí)現(xiàn)代理類外,Kotlin標(biāo)準(zhǔn)庫中也未我們提供了一些實(shí)現(xiàn)好的代理模式最欠。

lazy:lazy關(guān)鍵字在調(diào)用響應(yīng)的屬性時(shí)才會會執(zhí)行響應(yīng)的代理方法示罗,并且該方法只會調(diào)用一次。
示例代碼如下

class Person(){
    var name:String by Delegate()
    val age by lazy{
        Log.e("lazy","lazy")
        18
    };
}
       var person=Person();
        person.age
        person.age

測試結(jié)果

11-11 17:49:15.047 18817-18817/com.zhqy.javademo E/lazy: lazy

從測試結(jié)果可以看出雖然調(diào)用了兩次 person.age芝硬,但lazy的函數(shù)體只執(zhí)行了一次

Delegates.observable:當(dāng)屬性值發(fā)生改變時(shí)會調(diào)用.

示例代碼如下

class Person(){
    var name:String by Delegate()
    val age by lazy{
        Log.e("lazy","lazy")
        18
    };

    var gender:String by Delegates.observable("男性"){
        property, oldValue, newValue ->  Log.e("onchange","${property.name}:$oldValue:$newValue")
    }
}
       var person=Person();
        person.gender="女性"

測試結(jié)果如下

11-11 17:55:58.443 19182-19182/com.zhqy.javademo E/onchange: gender:男性:女性

其中property包含屬性的相關(guān)信息蚜点,oldValue是原先的屬性值,newValue為現(xiàn)在的屬性值拌阴。

by map:在類中尋找屬性名與Map<K,V>中key相同的再將數(shù)值賦給該屬性绍绘。

示例代碼如下

class Student( map:Map<String,Any>){
    val name:String by map;
    val age:Int by map

 }

 var map= mapOf<String,Any>("name" to "張三","age" to 18)
        var student=Student(map)
        Log.e("student","${student.name}:${student.age}")

測試結(jié)果

11-11 18:06:22.516 19482-19482/? E/student: 張三:18

以上就是本文的全部內(nèi)容

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子陪拘,更是在濱河造成了極大的恐慌厂镇,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件左刽,死亡現(xiàn)場離奇詭異捺信,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)欠痴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門迄靠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人喇辽,你說我怎么就攤上這事梨水。” “怎么了茵臭?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長舅世。 經(jīng)常有香客問我旦委,道長,這世上最難降的妖魔是什么雏亚? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任缨硝,我火速辦了婚禮,結(jié)果婚禮上罢低,老公的妹妹穿的比我還像新娘查辩。我一直安慰自己,他們只是感情好网持,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布宜岛。 她就那樣靜靜地躺著,像睡著了一般功舀。 火紅的嫁衣襯著肌膚如雪萍倡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天辟汰,我揣著相機(jī)與錄音列敲,去河邊找鬼。 笑死帖汞,一個(gè)胖子當(dāng)著我的面吹牛戴而,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播翩蘸,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼所意,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起扁眯,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤壮莹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后姻檀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體命满,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年绣版,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胶台。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡杂抽,死狀恐怖诈唬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缩麸,我是刑警寧澤铸磅,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站杭朱,受9級特大地震影響阅仔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜弧械,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一八酒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧刃唐,春花似錦羞迷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至抖甘,卻和暖如春报辱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背单山。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工碍现, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人米奸。 一個(gè)月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓昼接,卻偏偏與公主長得像,于是被迫代替她去往敵國和親悴晰。 傳聞我的和親對象是個(gè)殘疾皇子慢睡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

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