Kotlin 常用设计模式

212 阅读5分钟

创建型模式

单例模式

某个类的实例对象只有一个,适用于对象需要频繁实例化的场景。

饿汉式

在类初始化的时候就已经在内存中创建了对象,不存在线程安全问题。

object Singleton {
    
}

object 的单例在类加载时立即创建,而如果单例的初始化成本高,或者程序可能不会使用该单例,这会导致资源浪费。

懒汉式

在方法被调用时才创建对象,存在线程安全问题。

class Singleton private constructor() {

    companion object {
        private var instance: Singleton? = null
            get() {
                if (field == null) {
                    field = Singleton()
                }
                return field
            }

        fun get() = instance!!
    }

}

可以通过加锁来保证线程安全

class Singleton private constructor() {

    companion object {
        private var instance: Singleton? = null
            get() {
                if (field == null) {
                    field = Singleton()
                }
                return field
            }

        @Synchronized
        fun get() = instance!!
    }

}

静态内部类

外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化 instance,故不占内存,不存在线程安全问题。

class SingleTon private constructor() {

    companion object {
        fun getInstance() = SingleHolder.instance
    }

    private object SingleHolder {
        val instance = SingleTon()
    }
}

双重校验锁式

这里运用到 Kotlin 的延迟属性 lazy,Lazy 接收一个 lambda 并返回一个 Lazy 实例的函数,返回的实例可以作为实现延迟属性的委托,第一次调用 get() 会执行已传递给 lazy 的 lambda 表达式并记录结果, 后续再调用 get() 只是返回记录的结果,无线程安全问题。

class SingleTon private constructor() {
    companion object {
        val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { SingleTon() }
    }
}

工厂模式

帮助我们创建对象,隐藏对象创建过程的复杂度。

简单工厂模式

interface MobilePhone {
    fun produce()
}

class AndroidMobilePhone : MobilePhone {
    override fun produce() {
        print("produce AndroidMobilePhone")
    }
}

class IOSMobilePhone : MobilePhone {
    override fun produce() {
        print("produce IOSMobilePhone")
    }
}

enum class SystemType {
    ANDROID, IOS
}

class MobilePhoneFactory {
    companion object {
        fun createMobilePhone(type: SystemType) = when (type) {
            SystemType.ANDROID -> AndroidMobilePhone()
            SystemType.IOS -> IOSMobilePhone()
        }
    }
}

工厂方法模式

interface MobilePhone {
    fun produce()
}

class AndroidMobilePhone : MobilePhone {
    override fun produce() {
        print("produce AndroidMobilePhone")
    }
}

class IOSMobilePhone : MobilePhone {
    override fun produce() {
        print("produce IOSMobilePhone")
    }
}

abstract class MobilePhoneFactory {
    abstract fun createMobilePhone(): MobilePhone
}

class AndroidMobilePhoneFactory : MobilePhoneFactory() {
    override fun createMobilePhone(): MobilePhone {
        return AndroidMobilePhone()
    }
}

class IOSMobilePhoneFactory : MobilePhoneFactory() {
    override fun createMobilePhone(): MobilePhone {
        return IOSMobilePhone()
    }
}

抽象工厂模式

interface MobilePhone {
    fun produce()
}

class AndroidMobilePhone : MobilePhone {
    override fun produce() {
        print("produce AndroidMobilePhone")
    }
}

class IOSMobilePhone : MobilePhone {
    override fun produce() {
        print("produce IOSMobilePhone")
    }
}

interface Watch {
    fun produce()
}

class AndroidWatch : Watch {
    override fun produce() {
        print("produce AndroidWatch")
    }
}

class IOSWatch : Watch {
    override fun produce() {
        print("produce IOSWatch")
    }

}

//生产多个产品
abstract class Factory {
    abstract fun createMobilePhone(): MobilePhone
    abstract fun createWatch(): Watch
}

class AndroidFactory : Factory() {
    override fun createMobilePhone(): MobilePhone {
        return AndroidMobilePhone()
    }

    override fun createWatch(): Watch {
        return AndroidWatch()
    }
}

class IOSFactory : Factory() {
    override fun createMobilePhone(): MobilePhone {
        return IOSMobilePhone()
    }

    override fun createWatch(): Watch {
        return IOSWatch()
    }
}

建造者模式

将一个对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。

data class MobilePhone(
    var screen: String = "",
    var battery: String = "",
    var camera: String = ""
)

abstract class Builder {
    abstract fun buildScreen(screen: String): Builder
    abstract fun buildBattery(battery: String): Builder
    abstract fun buildCamera(camera: String): Builder
    abstract fun build(): MobilePhone
}

class MiBuilder : Builder() {

    private var mobilePhone = MobilePhone()

    override fun buildScreen(screen: String): Builder {
        mobilePhone.screen = screen
        return this
    }

    override fun buildBattery(battery: String): Builder {
        mobilePhone.battery = battery
        return this
    }

    override fun buildCamera(camera: String): Builder {
        mobilePhone.camera = camera
        return this
    }

    override fun build(): MobilePhone {
        return mobilePhone
    }

}

这是传统的建造者模式的实现方式,但对于 kotlin 来说,我们有更优雅的方式。

data class MobilePhone(
    var screen: String = "",
    var battery: String = "",
    var camera: String = ""
)

fun buildMobilePhone(action: MobilePhone.() -> Unit) = MobilePhone().apply(action)
val mobilePhone = buildMobilePhone {
    screen = "screen"
    battery = "battery"
    camera = "camera"
}

结构型模式

代理模式

通过代理对象访问目标对象

静态代理

interface MobilePhoneSale {
    fun sell()
}

class MobilePhoneSaleReal : MobilePhoneSale {
    override fun sell() {
        print("MainMobilePhoneSale sell")
    }
}

class MobilePhoneSaleProxy : MobilePhoneSale {
    private val mobilePhoneSaleReal = MobilePhoneSaleReal()
    override fun sell() {
        print("MobilePhoneSaleProxy sell")
        mobilePhoneSaleReal.sell()
    }
}

动态代理

interface MobilePhoneSale {
    fun sell()
}

class MobilePhoneSaleReal : MobilePhoneSale {
    override fun sell() {
        print("MainMobilePhoneSale sell")
    }
}

class MobilePhoneSaleProxy {
    private val real = MobilePhoneSaleReal()
    //在数组对象前加 * 号可以将数组展开,以方便传值
    fun getProxyInstance() = Proxy.newProxyInstance(
        real.javaClass.classLoader,
        real.javaClass.interfaces
    ) { _, p1, p2 -> p1.invoke(real, *p2.orEmpty()) } as MobilePhoneSale
}

装饰者模式

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

interface MobilePhone {
    fun fluency(): Float
    fun clarity(): Float
    fun produceDate(): String
}

class AppleMobilePhone : MobilePhone {
    override fun fluency() = 100f
    override fun clarity() = 90f
    override fun produceDate() = "2022-09-08"
}

abstract class MobilePhoneParts(val mobilePhone: MobilePhone) : MobilePhone

class PhoneSystem(mobilePhone: MobilePhone) : MobilePhoneParts(mobilePhone) {
    override fun fluency() = mobilePhone.fluency() + 1
    override fun clarity() = mobilePhone.clarity()
    override fun produceDate() = mobilePhone.produceDate()
}

class HDScreen(mobilePhone: MobilePhone) : MobilePhoneParts(mobilePhone) {
    override fun fluency() = mobilePhone.fluency()
    override fun clarity() = mobilePhone.clarity() + 1
    override fun produceDate() = mobilePhone.produceDate()
}
val phone = PhoneSystem(HDScreen(AppleMobilePhone()))

这是传统的装饰者模式实现方式,事实上,这种实现还是比较啰嗦的,比如 PhoneSystem 只装饰 fluency,却要把所有方法都重写一遍,不够优雅。我们可以借助 kotlin 的类委托特性,利用 by 关键字,将装饰类的所有方法委托给一个被装饰的类对象,然后只需覆写装饰的方法即可。

interface MobilePhone {
    fun fluency(): Float
    fun clarity(): Float
    fun produceDate(): String
}

class AppleMobilePhone : MobilePhone {
    override fun fluency() = 100f
    override fun clarity() = 90f
    override fun produceDate() = "2022-09-08"
}

abstract class MobilePhoneParts(val mobilePhone: MobilePhone) : MobilePhone by mobilePhone

class PhoneSystem(mobilePhone: MobilePhone) : MobilePhoneParts(mobilePhone) {
    override fun fluency() = mobilePhone.fluency() + 1
}

class HDScreen(mobilePhone: MobilePhone) : MobilePhoneParts(mobilePhone) {
    override fun clarity() = mobilePhone.clarity() + 1
}

行为型模式

观察者模式

定义了一对多的依赖关系,让一个或多个观察者对象监听一个主体对象。当被观察者状态发生改变时,需要通知相应的观察者,使这些观察者对象能够自动更新。

interface MobilePhonePriceListener {
    fun onRise(price: Int)
    fun onFall(price: Int)
}

//被观察者,使用委托属性监听值变化后通知
class PriceSubject {

    private val listeners = mutableSetOf<MobilePhonePriceListener>()
    var price: Int by Delegates.observable(0) { property, oldValue, newValue ->
        val isRise = newValue > oldValue
        listeners.forEach {
            if (isRise) {
                it.onRise(price)
            } else {
                it.onFall(price)
            }
        }
    }

    fun subscribe(observer: MobilePhonePriceListener) {
        listeners.add(observer)
    }

    fun unsubscribe(observer: MobilePhonePriceListener) {
        listeners.remove(observer)
    }
    
}

//观察者
class PhoneConsumer : MobilePhonePriceListener {
    override fun onRise(price: Int) {
        print("The price has risen. Don't buy it")
    }

    override fun onFall(price: Int) {
        print("The price has dropped, buy it")
    }
}
val priceSubject = PriceSubject()
priceSubject.subscribe(PhoneConsumer())
priceSubject.price = 10000

策略模式

当同一个操作,可能有不同表现的时候,可以将这个操作抽象出来,然后将具体的表现分别封装起来,并且都实现抽象的操作,这样在执行这个操作的时候,可以根据不同的表现类型,来执行不同表现。

interface Payment {
    fun pay()
}

class AliPayment : Payment {
    override fun pay() {
        print("Ali Pay")
    }
}

class WechatPayment : Payment {
    override fun pay() {
        print("Wechat pay")
    }
}

class PaymentContainer(private val payment: Payment) {
    fun pay() {
        payment.pay()
    }
}
val aliPay = PaymentContainer(AliPayment())
aliPay.pay()

val wechatPayment = PaymentContainer(WechatPayment())
wechatPayment.pay()