Kotlin特色风格实现gof设计模式

虽然设计模式偏重于思想层面,但是不同的编程语言有着其独特的语法展现,这使得在某个特定语言内,可能会更灵活和更有张力的实现某些设计模式。同时,对于kotlin来说,由于其完全兼容Java,若是只是谈设计模式的实现的话,完全可以把java实现的设计模式convert成kotlin就可以了,但是这样的话,便会埋没一些kotlin的特色。

Kotlin对比java而言,其大大扩大了函数的灵活性:高阶函数(可以接受函数作为参数),扩展函数(在一个类的外面,为其声明新的方法,静态编译,实例调用)以及独立函数(不依赖于类/对象,可以独立存在于文件中)等等,这使得其实现设计模式有其独特的风格和张力,因此,本文的目的,不仅仅是简单的用kotlin实现设计模式,而是专注于发现kotlin语言的特色风格和张力,同时研究kotlin这个现代语言的简洁性以及实现某些经典模式的便捷性。

本文只专注怎么用kotlin来进行比较特色的gof设计模式实现,基本不会探讨这些模式的思想和优缺点,需要的自行百度其它资料。本文还提供了安卓示例工程

接下来,我们先看看一些模式的实现。

策略模式

策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

  • 定义算法抽象,这里,不再是接口的方式,而是直接使用函数类型作为抽象;
typealias PlayVideo = () -> String
  • 算法实例对象,不再是类实例的方式,而是用子类型函数的方式,提供两个;
val tv: PlayVideo = {
    "用电视看视频"//作为返回值
}
val phone: PlayVideo = {
    "---用手机看视频---"
}
  • 算法的使用场景以及调用,tv和phone对象可以相互替换,产生不同行为
class Device(var name: String) {
    fun play(p: PlayVideo): String {
        return p()
    }
}
result.text = device.play(tv)//电视播放视频
result.text = device.play(phone)//手机播放视频

整体实现思路同java类似,只是这里将函数列为了一等公民,免去了对象的创建和调用,节省代码,更易理解。

命令模式

命令模式:将请求封装成对象,以便使用不同的请求、日志、队列等来参数化其他对象。命令模式也支持撤销操作。

  • 抽象命令,声明执行的方法;
typealias command = (worker: Worker) -> Unit
  • 命令接口实现”对象”,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作,在这里,是以函数对象的方式出现。
var strCommand: command = { it.addStr('a') }//后缀添加字符a
var numCommand: command = { it.addNum(9) }//后缀添加字符9
  • 接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
class Worker {
    var str: String = ""
    fun addStr(s: Char) {
        str += s
    }
    fun addNum(a: Int) {
        str += a
    }
    fun back() {
        str = str.substring(0, str.length - 1)
    }
}
  • 调用者,要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象,以供进行撤销、日志等操作。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
class Client(var aWorker: Worker) {
    var comList = ArrayList<command>()
    fun execute(com: command) {
        com.invoke(aWorker)
        comList.add(com)
    }
    fun undo() {
        if (comList.size == 0) {
            return
        }
        aWorker.back()
        comList.remove(comList[comList.size - 1])
    }
    fun show(): String {
        return aWorker.str
    }
}
  • 使用:创建具体的命令对象,并且设置命令对象的接收者
var client = Client(Worker())//创建调用者
client.execute(strCommand)//执行添加字符a的命令
client.execute(numCommand)//执行添加数字9的命令
client.undo()//撤销上一步的命令

观察者模式

观察者模式:有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

  • 定义观察者,是以函数对象的方式进行;
typealias listener=(a: Int) -> Unit
  • 被观察者,可以增加/删除观察者对象。
class Obsevable() {
    var lists: ArrayList<listener> = ArrayList()
    fun reg(p: listener) {
        lists.add(p)
    }
    fun unReg(p:listener) {
        lists.remove(p)
    }
    fun no(str: Int) {
        for (x in lists) {
            x.invoke(str)
        }
    }
}
  • 调用执行。
var observer = Obsevable()//声明被观察者对象
observer.reg { 
result.text = "${result.text}-观察者aaa1得到事件$it"
}//注册添加一个观察者,不能被取消注册
var v3: listener = { toast("v3得到事件$it") }//声明一个可被删除的观察者
observer.reg(v3)//注册添加一个观察者v3
observer.notify(110)//发生事件,通知观察者
observer.unReg(v3)//删除一个观察者v3

通过函数对象的整合,代码实现更加简约。

装饰者模式

在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。不过Kotlin有强大的扩展函数功能,装饰者的实现将会比较简约。

  • 定义行为抽象和最基础的行为;
interface Text {
    fun draw(): String
}
class DefaultText(var text: String) : Text {
    override fun draw(): String {
        return text
    }
}
  • 使用扩展函数,声明几个装饰行为。
fun Text.underline(decorated: Text.() -> String): String {
    return "_" + this.decorated() + "_"
}//给已有行为添加下划线_

fun Text.bracket(decorated: Text.() -> String): String {
    return "{" + this.decorated() + "}"
}//给已有行为添加花括号{}
  • 调用执行。
var text = DefaultText("装饰者")
result.text = text.draw()//基础行为
result.text = text.underline { text.draw() }//加下划线
result.text = text.bracket { text.underline { text.draw() } }//加下划线,再加括号

通过扩展函数,动态添加某些对象的行为是不是相当方便?

整体就先列出这么几个设计模式的实现吧,眼尖的童鞋可以发现,这些设计模式基本都是行为模式,这与kotlin强大且灵活的函数功能是分不开的。而对于其它类型的某些设计模式,kotlin比较难给出比较特色的实现,以后再讨论吧。

作者刘咸尚

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值