MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Kotlin设计模式实践案例解析

2022-06-234.5k 阅读

一、单例模式

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点。在 Kotlin 中,实现单例模式有多种方式。

1. 饿汉式单例

饿汉式单例在类加载时就创建实例,因此线程安全。

object SingletonEager {
    fun doSomething() {
        println("SingletonEager is doing something")
    }
}

在上述代码中,使用 object 关键字定义了一个单例对象 SingletonEagerobject 声明的对象在 Kotlin 中是饿汉式单例,在类加载时就被创建。可以通过 SingletonEager.doSomething() 来调用其方法。

2. 懒汉式单例(线程安全)

懒汉式单例在第一次使用时才创建实例。通过 synchronized 关键字来保证线程安全。

class SingletonLazy private constructor() {
    companion object {
        private var instance: SingletonLazy? = null
        @Synchronized
        fun getInstance(): SingletonLazy {
            if (instance == null) {
                instance = SingletonLazy()
            }
            return instance!!
        }
    }

    fun doSomething() {
        println("SingletonLazy is doing something")
    }
}

这里定义了一个私有的构造函数,防止外部创建实例。companion object 提供了一个静态方法 getInstance 来获取单例实例。@Synchronized 注解确保在多线程环境下只有一个实例被创建。使用时通过 SingletonLazy.getInstance().doSomething() 调用。

二、工厂模式

工厂模式是一种创建型设计模式,它提供了一种创建对象的方式,将对象的创建和使用分离。

1. 简单工厂模式

简单工厂模式定义了一个工厂类,用于创建对象。

abstract class Shape {
    abstract fun draw()
}

class Circle : Shape() {
    override fun draw() {
        println("Drawing a circle")
    }
}

class Rectangle : Shape() {
    override fun draw() {
        println("Drawing a rectangle")
    }
}

class ShapeFactory {
    companion object {
        fun createShape(shapeType: String): Shape? {
            return when (shapeType) {
                "circle" -> Circle()
                "rectangle" -> Rectangle()
                else -> null
            }
        }
    }
}

在上述代码中,Shape 是抽象类,CircleRectangle 是具体的形状类。ShapeFactory 是简单工厂类,其 createShape 方法根据传入的形状类型创建相应的形状对象。使用时可以这样:

fun main() {
    val circle = ShapeFactory.createShape("circle")
    circle?.draw()
    val rectangle = ShapeFactory.createShape("rectangle")
    rectangle?.draw()
}

2. 工厂方法模式

工厂方法模式将对象的创建延迟到子类中实现。

abstract class Product {
    abstract fun use()
}

class ConcreteProduct1 : Product() {
    override fun use() {
        println("Using ConcreteProduct1")
    }
}

class ConcreteProduct2 : Product() {
    override fun use() {
        println("Using ConcreteProduct2")
    }
}

abstract class Creator {
    abstract fun createProduct(): Product
    fun someOperation() {
        val product = createProduct()
        product.use()
    }
}

class ConcreteCreator1 : Creator() {
    override fun createProduct(): Product {
        return ConcreteProduct1()
    }
}

class ConcreteCreator2 : Creator() {
    override fun createProduct(): Product {
        return ConcreteProduct2()
    }
}

在这段代码中,Product 是抽象产品类,ConcreteProduct1ConcreteProduct2 是具体产品类。Creator 是抽象创建者类,createProduct 是抽象工厂方法。ConcreteCreator1ConcreteCreator2 是具体创建者类,实现了 createProduct 方法来创建具体的产品。使用时:

fun main() {
    val creator1 = ConcreteCreator1()
    creator1.someOperation()
    val creator2 = ConcreteCreator2()
    creator2.someOperation()
}

3. 抽象工厂模式

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

abstract class AbstractProductA {
    abstract fun operationA()
}

abstract class AbstractProductB {
    abstract fun operationB()
}

class ProductA1 : AbstractProductA() {
    override fun operationA() {
        println("ProductA1's operationA")
    }
}

class ProductA2 : AbstractProductA() {
    override fun operationA() {
        println("ProductA2's operationA")
    }
}

class ProductB1 : AbstractProductB() {
    override fun operationB() {
        println("ProductB1's operationB")
    }
}

class ProductB2 : AbstractProductB() {
    override fun operationB() {
        println("ProductB2's operationB")
    }
}

abstract class AbstractFactory {
    abstract fun createProductA(): AbstractProductA
    abstract fun createProductB(): AbstractProductB
}

class ConcreteFactory1 : AbstractFactory() {
    override fun createProductA(): AbstractProductA {
        return ProductA1()
    }

    override fun createProductB(): AbstractProductB {
        return ProductB1()
    }
}

class ConcreteFactory2 : AbstractFactory() {
    override fun createProductA(): AbstractProductA {
        return ProductA2()
    }

    override fun createProductB(): AbstractProductB {
        return ProductB2()
    }
}

在上述代码中,定义了抽象产品 AbstractProductAAbstractProductB 以及它们的具体实现。AbstractFactory 是抽象工厂类,定义了创建产品的抽象方法。ConcreteFactory1ConcreteFactory2 是具体工厂类,创建不同系列的产品。使用时:

fun main() {
    val factory1 = ConcreteFactory1()
    val productA1 = factory1.createProductA()
    val productB1 = factory1.createProductB()
    productA1.operationA()
    productB1.operationB()

    val factory2 = ConcreteFactory2()
    val productA2 = factory2.createProductA()
    val productB2 = factory2.createProductB()
    productA2.operationA()
    productB2.operationB()
}

三、代理模式

代理模式为其他对象提供一种代理以控制对这个对象的访问。

1. 静态代理

静态代理在编译时就已经确定代理类。

interface Subject {
    fun request()
}

class RealSubject : Subject {
    override fun request() {
        println("RealSubject is handling request")
    }
}

class ProxySubject(private val realSubject: RealSubject) : Subject {
    override fun request() {
        println("ProxySubject pre - processing")
        realSubject.request()
        println("ProxySubject post - processing")
    }
}

在这段代码中,Subject 是抽象主题接口,RealSubject 是真实主题类,ProxySubject 是代理类。代理类 ProxySubject 持有真实主题类 RealSubject 的实例,并在调用真实主题的 request 方法前后进行额外的处理。使用时:

fun main() {
    val realSubject = RealSubject()
    val proxySubject = ProxySubject(realSubject)
    proxySubject.request()
}

2. 动态代理

动态代理在运行时动态生成代理类。Kotlin 可以借助 Java 的动态代理机制来实现。

import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy

interface Subject {
    fun request()
}

class RealSubject : Subject {
    override fun request() {
        println("RealSubject is handling request")
    }
}

class DynamicProxy(private val target: Subject) : InvocationHandler {
    override fun invoke(proxy: Any, method: Method, args: Array<out Any>?): Any? {
        println("DynamicProxy pre - processing")
        val result = method.invoke(target, *args?: emptyArray())
        println("DynamicProxy post - processing")
        return result
    }

    fun getProxy(): Subject {
        return Proxy.newProxyInstance(
            target.javaClass.classLoader,
            target.javaClass.interfaces,
            this
        ) as Subject
    }
}

在上述代码中,DynamicProxy 实现了 InvocationHandler 接口,在 invoke 方法中进行代理处理。getProxy 方法用于获取动态代理实例。使用时:

fun main() {
    val realSubject = RealSubject()
    val dynamicProxy = DynamicProxy(realSubject)
    val proxy = dynamicProxy.getProxy()
    proxy.request()
}

四、观察者模式

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

import java.util.*

interface Observer {
    fun update(subject: Subject)
}

interface Subject {
    fun registerObserver(observer: Observer)
    fun removeObserver(observer: Observer)
    fun notifyObservers()
}

class ConcreteSubject : Subject {
    private val observers = ArrayList<Observer>()
    private var state: Int = 0

    fun getState(): Int {
        return state
    }

    fun setState(state: Int) {
        this.state = state
        notifyObservers()
    }

    override fun registerObserver(observer: Observer) {
        observers.add(observer)
    }

    override fun removeObserver(observer: Observer) {
        observers.remove(observer)
    }

    override fun notifyObservers() {
        for (observer in observers) {
            observer.update(this)
        }
    }
}

class ConcreteObserver(private val name: String) : Observer {
    override fun update(subject: Subject) {
        val concreteSubject = subject as ConcreteSubject
        println("$name observed state change to ${concreteSubject.getState()}")
    }
}

在上述代码中,Observer 接口定义了更新方法,Subject 接口定义了注册、移除和通知观察者的方法。ConcreteSubject 是具体主题类,维护观察者列表并在状态改变时通知观察者。ConcreteObserver 是具体观察者类,实现了更新方法。使用时:

fun main() {
    val subject = ConcreteSubject()
    val observer1 = ConcreteObserver("Observer1")
    val observer2 = ConcreteObserver("Observer2")
    subject.registerObserver(observer1)
    subject.registerObserver(observer2)
    subject.setState(10)
    subject.removeObserver(observer2)
    subject.setState(20)
}

五、策略模式

策略模式定义了一系列算法,将每个算法封装起来,并使它们可以相互替换。

interface Strategy {
    fun execute()
}

class ConcreteStrategyA : Strategy {
    override fun execute() {
        println("Executing ConcreteStrategyA")
    }
}

class ConcreteStrategyB : Strategy {
    override fun execute() {
        println("Executing ConcreteStrategyB")
    }
}

class Context(private val strategy: Strategy) {
    fun executeStrategy() {
        strategy.execute()
    }
}

在这段代码中,Strategy 是抽象策略接口,ConcreteStrategyAConcreteStrategyB 是具体策略类。Context 类持有一个策略对象,并通过 executeStrategy 方法执行相应的策略。使用时:

fun main() {
    val strategyA = ConcreteStrategyA()
    val contextA = Context(strategyA)
    contextA.executeStrategy()

    val strategyB = ConcreteStrategyB()
    val contextB = Context(strategyB)
    contextB.executeStrategy()
}

六、装饰器模式

装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。

interface Component {
    fun operation()
}

class ConcreteComponent : Component {
    override fun operation() {
        println("ConcreteComponent is operating")
    }
}

abstract class Decorator(private val component: Component) : Component {
    override fun operation() {
        component.operation()
    }
}

class ConcreteDecoratorA(private val component: Component) : Decorator(component) {
    override fun operation() {
        println("ConcreteDecoratorA pre - processing")
        super.operation()
        println("ConcreteDecoratorA post - processing")
    }
}

class ConcreteDecoratorB(private val component: Component) : Decorator(component) {
    override fun operation() {
        println("ConcreteDecoratorB pre - processing")
        super.operation()
        println("ConcreteDecoratorB post - processing")
    }
}

在上述代码中,Component 是抽象组件接口,ConcreteComponent 是具体组件类。Decorator 是抽象装饰器类,持有一个组件对象。ConcreteDecoratorAConcreteDecoratorB 是具体装饰器类,在调用组件的 operation 方法前后添加额外的处理。使用时:

fun main() {
    val component = ConcreteComponent()
    val decoratorA = ConcreteDecoratorA(component)
    val decoratorB = ConcreteDecoratorB(decoratorA)
    decoratorB.operation()
}

七、适配器模式

适配器模式将一个类的接口转换成客户希望的另一个接口。

1. 类适配器

类适配器通过继承来实现。

class Adaptee {
    fun specificRequest() {
        println("Adaptee's specific request")
    }
}

interface Target {
    fun request()
}

class ClassAdapter : Adaptee(), Target {
    override fun request() {
        specificRequest()
    }
}

在这段代码中,Adaptee 是需要适配的类,Target 是目标接口。ClassAdapter 继承 Adaptee 并实现 Target 接口,将 AdapteespecificRequest 方法适配成 Targetrequest 方法。使用时:

fun main() {
    val adapter = ClassAdapter()
    adapter.request()
}

2. 对象适配器

对象适配器通过组合来实现。

class Adaptee {
    fun specificRequest() {
        println("Adaptee's specific request")
    }
}

interface Target {
    fun request()
}

class ObjectAdapter(private val adaptee: Adaptee) : Target {
    override fun request() {
        adaptee.specificRequest()
    }
}

这里 ObjectAdapter 持有 Adaptee 的实例,并在 request 方法中调用 AdapteespecificRequest 方法。使用时:

fun main() {
    val adaptee = Adaptee()
    val adapter = ObjectAdapter(adaptee)
    adapter.request()
}

八、命令模式

命令模式将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

interface Command {
    fun execute()
}

class Receiver {
    fun action() {
        println("Receiver is performing action")
    }
}

class ConcreteCommand(private val receiver: Receiver) : Command {
    override fun execute() {
        receiver.action()
    }
}

class Invoker(private val command: Command) {
    fun invoke() {
        command.execute()
    }
}

在上述代码中,Command 是抽象命令接口,Receiver 是真正执行操作的类。ConcreteCommand 是具体命令类,持有 Receiver 的实例并实现 execute 方法。Invoker 是调用者类,持有命令对象并调用其 execute 方法。使用时:

fun main() {
    val receiver = Receiver()
    val command = ConcreteCommand(receiver)
    val invoker = Invoker(command)
    invoker.invoke()
}

九、模板方法模式

模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中实现。

abstract class AbstractClass {
    final fun templateMethod() {
        step1()
        step2()
        step3()
    }

    open fun step1() {
        println("AbstractClass's step1")
    }

    abstract fun step2()

    open fun step3() {
        println("AbstractClass's step3")
    }
}

class ConcreteClass : AbstractClass() {
    override fun step2() {
        println("ConcreteClass's step2")
    }
}

在这段代码中,AbstractClass 定义了 templateMethod 方法作为算法骨架,包含 step1step2step3 步骤。step1step3 有默认实现,step2 是抽象方法,由子类 ConcreteClass 实现。使用时:

fun main() {
    val concreteClass = ConcreteClass()
    concreteClass.templateMethod()
}

十、迭代器模式

迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

interface Iterator<out T> {
    fun hasNext(): Boolean
    fun next(): T
}

interface Aggregate<out T> {
    fun iterator(): Iterator<T>
}

class ConcreteAggregate(private val items: List<Int>) : Aggregate<Int> {
    override fun iterator(): Iterator<Int> {
        return ConcreteIterator(items)
    }
}

class ConcreteIterator(private val items: List<Int>) : Iterator<Int> {
    private var index = 0
    override fun hasNext(): Boolean {
        return index < items.size
    }

    override fun next(): Int {
        val item = items[index]
        index++
        return item
    }
}

在上述代码中,Iterator 接口定义了迭代的方法,Aggregate 接口定义了获取迭代器的方法。ConcreteAggregate 是具体聚合类,ConcreteIterator 是具体迭代器类。使用时:

fun main() {
    val aggregate = ConcreteAggregate(listOf(1, 2, 3, 4, 5))
    val iterator = aggregate.iterator()
    while (iterator.hasNext()) {
        println(iterator.next())
    }
}