有趣的设计模式

设计模式

单一职责原则

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

比如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("消息来啦😭😊")
}

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

相关推荐
diaostar2 小时前
Android OKHttp原理简单说明
android·okhttp
b2894lxlx4 小时前
flutter3.29 build.gradle.kts设置安卓签名
android·flutter
androidwork5 小时前
Kotlin扩展函数提升Android开发效率
android·开发语言·kotlin
居然是阿宋5 小时前
Android SDK 开发中的 AAR 与 JAR 区别详解
android·java·jar
练习本6 小时前
AI大模型驱动的智能座舱研发体系重构
android·人工智能·重构·架构
姜行运6 小时前
C++【继承】
android·开发语言·c++
pq113_66 小时前
OrangePi Zero 3学习笔记(Android篇)1 - 搭建环境
android·orangepi zero 3
志存高远6611 小时前
kotlin 扩展函数
android·开发语言·kotlin
小镇敲码人13 小时前
【深入浅出MySQL】之数据类型介绍
android·数据库·mysql
柯南二号14 小时前
Android 实现一个隐私弹窗
android