iT邦幫忙

2024 iThome 鐵人賽

DAY 19
0

介紹

Kotlin 也有內建觀察模式,只要使用Delegates.observable就行,但是抽象類別沒有初始值的關係,所以不能直接用

觀察者模式實作

因為 Java 的範例有抽象類別,所以就先不用Delegates.observable

  1. 建立會員系統觀察者
abstract class MemberObserver(val name: String) {
    abstract fun getRegister(isRegister: Boolean): String
}
  1. 建立全家使用者,繼承會員系統觀察者
class FamilyMark(name: String) : MemberObserver(name) {

    override fun getRegister(isRegister: Boolean): String {
        val text = StringBuilder()

        text.append("全家使用者: ")
        text.append(this.name)
        text.append(" / ")
        text.append("註冊狀態: ")

        if (isRegister) {
            text.append("資料填寫完整")
        } else {
            text.append("資料填寫缺漏")
        }

        return text.toString()
    }
}
  1. 建立家樂福使用者,繼承會員系統觀察者
class Carrefour(name: String) : MemberObserver(name) {

    override fun getRegister(isRegister: Boolean): String {
        val text = StringBuilder()

        text.append("家樂福使用者: ")
        text.append(this.name)
        text.append(" / ")
        text.append("註冊狀態: ")

        if (isRegister) {
            text.append("資料填寫完整")
        } else {
            text.append("資料填寫缺漏")
        }

        return text.toString()
    }
}
  1. 建立會員系統被觀察者
abstract class MemberSubject {

    protected var memberObserverList: MutableList<MemberObserver> = ArrayList()

    fun add(memberObserver: MemberObserver): String {
        val text = StringBuilder()

        text.append("新增: ")
        text.append(memberObserver.name)
        text.append(" - ")

        if (memberObserverList.add(memberObserver)) {
            text.append("新增成功")
        } else {
            text.append("新增失敗")
        }

        text.append("\n")
        return text.toString()
    }

    fun remove(memberObserver: MemberObserver): String {
        val text = StringBuilder()

        text.append("移除: ")
        text.append(memberObserver.name)
        text.append(" - ")

        if (memberObserverList.remove(memberObserver)) {
            text.append("移除成功")
        } else {
            text.append("移除失敗")
        }

        text.append("\n")
        return text.toString()
    }

    abstract fun getRegister(isRegister: Boolean): String?
}
  1. 建立購物中心被觀察者
class Mall : MemberSubject() {

    override fun getRegister(isRegister: Boolean): String? {
        val text = StringBuilder()

        text.append("\n")

        for (memberObserver in memberObserverList) {
            text.append(memberObserver.getRegister(isRegister))
            text.append(" / ")
            if (isRegister) {
                text.append("執行註冊")
            } else {
                text.append("不執行註冊")
            }

            text.append("\n")
        }
        text.append("\n")

        return text.toString()
    }
}

觀察者模式測試

  1. 測試案例
@Test
fun show() {
    
    val text = StringBuilder()
    text.append("\n")
    
    val familyMarkAndy: MemberObserver = FamilyMark("Andy")
    val familyMarkMark: MemberObserver = FamilyMark("Mark")
    val carrefour: MemberObserver = Carrefour("AWD")
    
    val mall: MemberSubject = Mall()
    
    text.append(mall.add(familyMarkAndy))
    text.append(mall.add(familyMarkMark))
    text.append(mall.add(carrefour))
    
    text.append(mall.getRegister(true))
    
    text.append(mall.remove(familyMarkAndy))
    
    text.append(mall.getRegister(false))
    
    text.append(mall.remove(familyMarkMark))
    text.append(mall.remove(carrefour))
    
    text.append(mall.getRegister(false))
    
    assertEquals("測試", text.toString())
}
  1. 執行測試
新增: Andy - 新增成功
新增: Mark - 新增成功
新增: AWD - 新增成功

全家使用者: Andy / 註冊狀態: 資料填寫完整 / 執行註冊
全家使用者: Mark / 註冊狀態: 資料填寫完整 / 執行註冊
家樂福使用者: AWD / 註冊狀態: 資料填寫完整 / 執行註冊

移除: Andy - 移除成功

全家使用者: Mark / 註冊狀態: 資料填寫缺漏 / 不執行註冊
家樂福使用者: AWD / 註冊狀態: 資料填寫缺漏 / 不執行註冊

移除: Mark - 移除成功
移除: AWD - 移除成功

上一篇
113/18 - 觀察者模式(Observer)- Java
下一篇
113/20 - 策略模式(Strategy)- Java
系列文
肯定會斷賽之在 Android 開發使用設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言