iT邦幫忙

2024 iThome 鐵人賽

DAY 29
0

介紹

還是一樣,Kotlin 沒有中介者模式的語法糖,只有寫法上的差別

功能需求如下:

  1. 有三個角色,分別是商場、家樂福和全家
  2. 商場可以對家樂福和全家廣播促銷活動
  3. 家樂福和全家可以互相傳訊息支援
  4. 家樂福和全家不能使用廣播

中介者模式實作

  1. 建立中介者介面
    • 訊息(send)
    • 廣播(sendAllStore)
interface Mediator {
    fun send(name: String, message: String, sendTo: Caller): String

    fun sendAllStore(name: String, message: String): String
}
  1. 建立抽象類別
abstract class Caller(val name: String) {

    private val mediator: Mediator = CallerMediator()

    fun send(message: String, caller: Caller): String {
        val send = mediator.send(this.name, message, caller)
        return send
    }

    open fun sendAllStore(message: String): String {
        val sendAllStore = mediator.sendAllStore(this.name, message)
        return sendAllStore
    }
}
  1. 建立中介者類別
    • 增加角色(addCaller)
    • 實作訊息(send)
    • 實作廣播(sendAllStore)
class CallerMediator : Mediator {

    companion object {
        const val MANAGER = "Manager"
        const val STAFF = "Staff"
    }

    private val managerList = mutableListOf<Manager>()
    private val staffList = mutableListOf<Staff>()

    fun addCaller(caller: Caller): String {
        val text = StringBuilder()

        if (MANAGER == caller.javaClass.simpleName) {
            managerList.add(caller as Manager)
            text.append("加入管理級廣播群組:")
        } else if (STAFF == caller.javaClass.simpleName) {
            staffList.add(caller as Staff)
            text.append("加入員工級訊息群組:")
        } else {
            text.append("不加入聊天群組:")
        }

        text.append(caller.name)
        return text.toString()
    }

    override fun send(name: String, message: String, sendTo: Caller): String {
        val text = StringBuilder()
        text.append(name)
        text.append(" ")
        text.append("發送訊息給 ")

        managerList.forEach {
            if (it.name == name) {
                text.append(sendTo.name)
            }
        }

        staffList.forEach {
            if (it.name == name) {
                text.append(sendTo.name)
            }
        }
        text.append(" | ")
        text.append("訊息內容:")
        text.append(message)

        return text.toString()
    }

    override fun sendAllStore(name: String, message: String): String {
        val text = StringBuilder()
        text.append(name)
        text.append(" ")
        text.append("發送全體廣播:")
        text.append(message)
        text.append("\n")
        text.append("接收者:")

        managerList.forEach {
            if (it.name != name) {
                text.append(it.name)
                text.append("、")
            }
        }

        staffList.forEach {
            if (it.name != name) {
                text.append(it.name)
                text.append("、")
            }
        }

        return text.toString()
    }
}
  1. 增加管理者,有權限廣播和訊息
class Manager(name: String) : Caller(name)
  1. 增加員工,只能傳送訊息
class Staff(name: String) : Caller(name) {

    override fun sendAllStore(message: String): String {
        val text = StringBuilder()
        text.append(name)
        text.append(" 無法使用全體廣播")
        return text.toString()
    }
}

中介者模式測試

  1. 測試案例
class KotlinTest {

    @Test
    fun show() {

        val text = StringBuilder()
        text.append("\n")

        val mall: Caller = Manager("商場")
        val carrefour: Caller = Staff("家樂福")
        val familyMark: Caller = Staff("全家")

        val callerMediator = CallerMediator()
        text.append(callerMediator.addCaller(mall))
        text.append("\n")
        text.append(callerMediator.addCaller(carrefour))
        text.append("\n")
        text.append(callerMediator.addCaller(familyMark))
        text.append("\n")
        text.append("\n")
        text.append(mall.sendAllStore("現在飲料買一送五"))
        text.append("\n")
        text.append("\n")
        text.append(mall.send("現在麵包買二送一,賣完了自己想辦法生出麵包", carrefour))
        text.append("\n")
        text.append(mall.send("現在便當打七折,賣完了自己想辦法生出便當", familyMark))
        text.append("\n")
        text.append(carrefour.send("借我一個員工支援收銀", familyMark))
        text.append("\n")
        text.append(familyMark.send("借你一個員工時薪 2000 元", carrefour))
        text.append("\n")
        text.append("\n")
        text.append(carrefour.sendAllStore("我不賣麵包啦,商場"))
        text.append("\n")
        text.append(familyMark.sendAllStore("我不賣便當啦,商場"))
        text.append("\n")

        assertEquals("測試", text.toString())
    }
}
  1. 執行測試
加入管理級廣播群組:商場
加入員工級訊息群組:家樂福
加入員工級訊息群組:全家

商場 發送全體廣播:現在飲料買一送五
接收者:

商場 發送訊息給  | 訊息內容:現在麵包買二送一,賣完了自己想辦法生出麵包
商場 發送訊息給  | 訊息內容:現在便當打七折,賣完了自己想辦法生出便當
家樂福 發送訊息給  | 訊息內容:借我一個員工支援收銀
全家 發送訊息給  | 訊息內容:借你一個員工時薪 2000 元

家樂福 無法使用全體廣播
全家 無法使用全體廣播

上一篇
113/28 - 中介者模式(Mediator)- Java
下一篇
113/30 - 寫在結束 - 賽後心得
系列文
肯定會斷賽之在 Android 開發使用設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言