有趣的设计模式

设计模式

单一职责原则

定义:一个类的职责单一。

比如Person类,不应该包含人类以为的职责。

开放封闭原则

定义:对类、模块、函数的拓展开发,修改封闭。

里氏替换原则

定义:所有引入基类的地方必须能够透明的使用其子类的对象。

依赖倒置原则

定义:高层模块不应该依赖底层模块的细节,而应该依赖抽象。

例如:USB接口的抽象。

迪米特原则

定义:一个软件实体应当尽可能少的与其他实体发生相互作用。

注意:

  • 类的访问权限最低
  • 类之间的相互引入最低
  • 系统耦合度最低

接口隔离原则

定义:一个类对另一个类的依赖应该建立在最小的接口上。

注意:

  • 禁止臃肿的接口,将其拆分为小而美的接口

单例模式

DCL写法

kotlin 复制代码
class Singleton private constructor() {
    companion object {
        @Volatile
        private var instance: Singleton? = null
        fun getInstance(): Singleton {
            return instance ?: synchronized(this) {
                instance ?: Singleton().also { instance = it }
            }
        }
    }
}

静态内部类

kotlin 复制代码
class Singleton2 private constructor() {
    private class SingletonHolder {
        companion object {
            @JvmStatic
            val instance = Singleton2()
        }
    }
    companion object {
        @JvmStatic
        fun getInstance(): Singleton2 {
            return SingletonHolder.instance
        }
    }
}

by lazy

kotlin 复制代码
class Singleton private constructor() {
    companion object {
        val instance: Singleton by lazy {
            Singleton()
        }
    }
}

简单工厂模式

注意: 简单工厂模式不属于23种设计模式

kotlin 复制代码
abstract class Computer{
    abstract fun getComputer(): String
}

class MacBook : Computer() {
    override fun getComputer(): String {
        return "MacBook"
    }
}

class Windows : Computer() {
    override fun getComputer(): String {
        return "Windows"
    }
}

class Linux : Computer() {
    override fun getComputer(): String {
        return "Linux"
    }
}


class ComputerFactory {
    companion object {
        fun createComputer(type: String): Computer {
            return when (type) {
                "MacBook" -> MacBook()
                "Windows" -> Windows()
                "Linux" -> Linux()
                else -> throw IllegalArgumentException("Unknown computer type")
            }
        }
    }
}

fun main() {
    ComputerFactory.createComputer("MacBook").getComputer().let { println(it) }
}

工厂方法模式

kotlin 复制代码
abstract class Computer{
    abstract fun getComputer(): String
}

class Mac1Book : Computer() {
    private val cpu: String = "M1"
    override fun getComputer(): String {
        return "MacBoo1k:cpu:$cpu"
    }
}

class LenovoBook : Computer() {
    private val cpu: String = "i7"
    override fun getComputer(): String {
        return "LenovoBook:cpu:$cpu"
    }
}


abstract class ComputerFactory {
    abstract fun <T : Computer> createComputer(kClazz: KClass<T>): Computer
}

class MacComputerFactory : ComputerFactory() {
    override fun <T : Computer> createComputer(kClazz: KClass<T>): Computer {
        return kClazz.createInstance()
    }
}

class WindowsComputerFactory : ComputerFactory() {
    override fun <T : Computer> createComputer(kClass: KClass<T>): Computer {
        return kClass.createInstance()
    }
}

class Programmer{
    fun programme(computer: Computer){
        println("程序员在${computer.getComputer()}上编程...")
    }
}


fun main() {
    val programmer = Programmer()
    programmer.programme(
        MacComputerFactory().createComputer(Mac1Book::class)
    )
    programmer.programme(
        WindowsComputerFactory().createComputer(LenovoBook::class)
    )
}

工厂模式在很多地方都有使用,多么优雅。程序员只需要更好电脑即可在不同的电脑上进行编程,非常符合现实生活中的场景,并且也符合开闭原则。

建造者模式

kotlin 复制代码
class Computer private constructor(
    builder: Builder
) {

    private val cpu: String = builder.cpu
    private val ram: String = builder.ram
    private val disk: String = builder.disk
    private val gpu: String = builder.gpu
    private val os: String = builder.os

    open class Builder{
        internal var cpu: String = "cpu"
        internal var ram: String = "ram"
        internal var disk: String = "disk"
        internal var gpu: String = "gpu"
        internal var os: String = "os"
        fun cpu(cpu: String) = apply { this.cpu = cpu }
        fun ram(ram: String) = apply { this.ram = ram }
        fun disk(disk: String) = apply { this.disk = disk }
        fun gpu(gpu: String) = apply { this.gpu = gpu }
        fun os(os: String) = apply { this.os = os }
        fun build() = Computer(this)
    }
    fun show() {
        println("cpu: $cpu, ram: $ram, disk: $disk, gpu: $gpu, os: $os")
    }

    /**
     * 不同的建造者实现不同的建造方式
     */
    class MacBuilder : Builder()

}

fun main() {
    val computer = Computer.Builder()
        .cpu("Intel")
        .ram("16GB")
        .disk("1TB")
        .gpu("NVIDIA")
        .build()
    computer.show()
    val mac: Computer = Computer.MacBuilder()
        .cpu("Apple M1")
        .ram("16GB")
        .disk("512GB")
        .gpu("Apple GPU")
        .os("macOS Monterey")
        .build()
    mac.show()
}

代理模式

静态代理

kotlin 复制代码
interface SmsService {
    fun send(message: String?): String?
}

class SmsServiceImpl : SmsService {
    override fun send(message: String?): String? {
        println("send message:$message")
        return message
    }
}

class SmsServiceProxy(
    private val smsService: SmsService
) : SmsService {
    override fun send(message: String?): String? {
        println("before send message")
        val result = smsService.send(message)
        println("after send message")
        return result
    }}

fun main() {
    val smsService: SmsService = SmsServiceProxy(SmsServiceImpl())
    smsService.send("hello world")
}

动态代理

by 关键字

kotlin 复制代码
interface Base {
    fun print()
}

class BaseImpl(val x: Int) : Base {
    override fun print() { println("x: $x") }
}
class BaseImpl1(val x: Int) : Base {
    override fun print() { println("1 -> x: $x") }
}

class Derived(private val b: Base) : Base by b {
    // 这里的 b 是一个委托对象
    // 通过委托对象来实现接口 Base 的方法
    // 也可以在这里添加其他方法或属性
    override fun print() {
        println("before...")
        // 调用委托对象的 print 方法
        b.print()
        println("after...")
    }
}


fun main() {
    val b = BaseImpl(10)
    Derived(b).print() // 输出 10
    val b1 = BaseImpl1(20)
    Derived(b1).print() // 输出 20
}

jdk

kotlin 复制代码
class DebugInvocationHandler(
    /**
     * 代理类中的真实对象
     */
    private val target: Any?
) : InvocationHandler {
    @Throws(InvocationTargetException::class, IllegalAccessException::class)
    override fun invoke(proxy: Any?, method: Method, args: Array<Any?>): Any? {
        // 调用方法之前,我们可以添加自己的操作
        println("before method " + method.name)
        val result = method.invoke(target, *args)
        // 调用方法之后,我们同样可以添加自己的操作
        println("after method " + method.name)
        return result
    }
}

object JdkProxyFactory {
    fun getProxy(target: Any): Any {
        return Proxy.newProxyInstance(
            target.javaClass.getClassLoader(),  // 目标类的类加载器
            target.javaClass.interfaces,  // 代理需要实现的接口,可指定多个
            DebugInvocationHandler(target) // 代理对象对应的自定义 InvocationHandler
        )
    }
}

interface SmsService {
    fun send(message: String?): String?
}

class SmsServiceImpl : SmsService {
    override fun send(message: String?): String? {
        println("send message:$message")
        return message
    }
}

fun main() {
    val smsService: SmsService = JdkProxyFactory.getProxy(SmsServiceImpl()) as SmsService
    smsService.send("hello world")
}

装饰模式

kotlin 复制代码
abstract class Person(
    private val name: String = "Person",
) {
    open fun show(){
        println("person ${name}: 赤身裸体...")
    }
    open fun run(){
        println("person ${name}: 用脚跑...")
    }
}

class Student(
    name: String = "Tom",
) : Person(name) {
    override fun show() {
        // 穿校服
    }
    override fun run() {
        println("student 用脚跑...")
    }
}

/**
 * 给人穿衣服、眼镜、跑车
 */
abstract class Clothing(private val person: Person) : Person(){
    override fun show() {
        person.show()
    }
}



class Shoe(clothing: Clothing) : Clothing(person = clothing) {
    override fun show() {
        super.show()
        println("Shoe show...")
    }
}


class Jacket(person: Person) : Clothing(person = person) {
    override fun show() {
        super.show()
        println("Jacket show...")
    }
}

class TShirt(person: Person) : Clothing(person = person) {
    override fun show() {
        super.show()
        println("TShirt show...")
    }
}

class SchoolUniform(person: Person) : Clothing(person){
    override fun show() {
        super.show()
        println("SchoolUniform show...")
    }
}

abstract class Trip(person: Person) : Person() {
    override fun run() {}
}

class Lamborghini(person: Person) : Trip(person = person) {
    override fun run() {
        super.run()
        println("Lamborghini run...")
        pickup()
    }
    private fun pickup(){
        println("Lamborghini pick up with girlfriend ...")
    }
}

class Minibus(person: Person) : Trip(person = person) {
    override fun run() {
        super.run()
        println("Minibus run...")
        pickup()
    }

    /**
     * 😭和女朋友分手...
     */
    private fun pickup(){
        println("Minibus pick up with dog ...")
    }
}


fun main() {
    // 学生
    val student = Student(name = "Jerry")
    val schoolUniform = SchoolUniform(student) // 先穿衣服,后穿鞋
    val schoolShoe = Shoe(schoolUniform)       // 加强
    val schoolJacket = Jacket(schoolShoe)       // 加强
    val schoolTShirt = TShirt(schoolJacket)     // 加强
    schoolTShirt.show()
    // 上学开跑车
    val lamborghini = Lamborghini(schoolTShirt)
    lamborghini.run()
    // 之后破产开面包车
    val minibus = Minibus(schoolTShirt)
    minibus.run()
    // 逆风翻盘继续开跑车
    lamborghini.run()
}

你会神奇的发现增强一个Person类,完全不需要修改原有的代码,符合开闭原则。

外观模式

kotlin 复制代码
class SubSystem1 {
    fun method1(): String {
        println("SubSystem1: method1")
        return "hello"
    }
}

class SubSystem2 {
    fun method2(): String {
        println("SubSystem2: method2")
        return "world"
    }
}

class Facade {
    private val subSystem1 = SubSystem1()
    private val subSystem2 = SubSystem2()

    fun method(): String {
        return "${subSystem1.method1()} ${subSystem2.method2()}"
    }
}

fun main() {
    println(Facade().method())
}

以上是最简单的外观模式的体现,通过外观类Facade将子系统的接口进行组合,然后将外观类的接口提供给客户端使用。

注意:

  • 子系统之间不能直接耦合
  • 对于子系统符合开闭原则

享元模式

场景:1亿用户购买IPhone

IPhone15

  • 128G ¥4599
  • 256G ¥5599
  • 512G ¥7599

IPhone16

  • 128G ¥5199
  • 256G ¥5999
  • 512G ¥8199
kotlin 复制代码
interface Goods{
    val price : Int
}

data class IPhone15(
    val name: String = "IPhone15",
    var disk: Int = 128,
) : Goods {
    /**
     * *   128G ¥5199
     * *   256G ¥5999
     * *   512G ¥8199
     */
    override val price: Int
        get() {
            return when(disk){
                128 -> 4599
                256 -> 5599
                512 -> 7599
                else -> throw IllegalArgumentException("无此硬盘")
            }
        }
    init {
        println("IPhone15 init")
    }

    override fun toString(): String {
        return "IPhone15(name='$name', disk=$disk, price=$price)"
    }

}

data class IPhone16(
    val name: String = "IPhone16",
    var disk: Int = 128,
) : Goods {
    /**
     * *   128G ¥5199
     * *   256G ¥5999
     * *   512G ¥8199
     */
    override val price: Int
        get() {
            return when(disk){
                128 -> 5199
                256 -> 5999
                512 -> 8199
                else -> throw IllegalArgumentException("无此硬盘")
            }
        }
    init {
        println("IPhone16 init")
    }

    override fun toString(): String {
        return "IPhone16(name='$name', disk=$disk, price=$price)"
    }

}


object IPhoneFactory{
    val pool: MutableMap<KClass<*>, Goods> = mutableMapOf()
    fun <T : Goods> getIPhone(kClass: KClass<T>): T {
        @Suppress("UNCHECKED_CAST")
        return pool.getOrPut(key = kClass){
            kClass.createInstance()
        } as T
    }
}


fun main() {
    for(i in 0 until 10){
        val iPhone15: IPhone15 = IPhoneFactory.getIPhone(IPhone15::class)
        iPhone15.disk = 128
        println(iPhone15)
        iPhone15.disk = 256
        println(iPhone15)
        iPhone15.disk = 512
        println(iPhone15)
        val iPhone16: IPhone16 = IPhoneFactory.getIPhone(IPhone16::class)
        iPhone16.disk = 128
        println(iPhone16)
        iPhone16.disk = 256
        println(iPhone16)
        iPhone16.disk = 512
        println(iPhone16)
    }
}

策略模式

kotlin 复制代码
interface Strategy{
    fun pay(): Result<Boolean>
}

class AliPay : Strategy {
    override fun pay(): Result<Boolean> {
        println("支付宝支付...")
        return Result.success(true)
    }
}

class WechatPay : Strategy{
    override fun pay(): Result<Boolean> {
        println("微信支付...")
        return Result.success(true)
    }

}

class PayContext(
    private var strategy: Strategy
){
    fun setStrategy(strategy: Strategy){
        this.strategy = strategy
    }
    fun pay(): Result<Boolean>{
        return strategy.pay()
    }
}

fun main() {
    val payContext = PayContext(AliPay())
    println(payContext.pay())
    payContext.setStrategy(WechatPay())
    println(payContext.pay())
}

如果有其他的支付策略,只需要实现支付策略类即可,满足开闭原则。

模板方法模式

Android中的四大组件的生命周期函数的定义就是使用的模板方法模式。

观察者模式

kotlin 复制代码
interface Observer<T>{
    fun update(data: T)
}

interface Subject<T>{
    fun add(observer: Observer<T>)
    fun remove(observer: Observer<T>)
    fun notify(data: T)
}

class MessageSubject<T> : Subject<T> {
    private val observers: MutableList<Observer<T>> = mutableListOf()
    override fun add(observer: Observer<T>) {
        observers.add(observer)
    }

    override fun remove(observer: Observer<T>) {
        observers.remove(observer)
    }

    override fun notify(data: T) {
        observers.forEach { it.update(data = data) }
    }
}

class User<T>(private val name: String) : Observer<T>{
    override fun update(data: T) {
        println("name: $name, data: $data")
    }
}

fun main() {
    val user1 = User<String>(name = "user1")
    val user2 = User<String>(name = "user2")
    val messageSubject = MessageSubject<String>()
    messageSubject.add(user1)
    messageSubject.add(user2)
    messageSubject.notify("消息来啦😭😊")
}

设计模式介绍完毕,有什么不足请各位大佬指出,我会继续完善的。😊

相关推荐
帅次8 分钟前
Flutter DropdownButton 详解
android·flutter·ios·kotlin·gradle·webview
际宇人13 分钟前
移动端APP阿里云验证码2.0接入实录
android
.又是新的一天.27 分钟前
02_MySQL安装及配置
android·数据库·mysql
QING6181 小时前
Kotlin groupBy用法及代码示例
android·kotlin·源码阅读
QING6181 小时前
Kotlin getOrElse用法及代码示例
android·kotlin·源码阅读
QING6181 小时前
Kotlin getOrNull用法及代码示例
android·kotlin·源码阅读
QING6181 小时前
Kotlin getValue用法及代码示例
android·kotlin·源码阅读
QING6181 小时前
Kotlin getOrPut用法及代码示例
android·kotlin·源码阅读
QING6181 小时前
Kotlin groupingBy用法及代码示例
android·kotlin·源码阅读
祖师爷科技1 小时前
kotlin扩展函数的实现原理
android·kotlin