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

Kotlin中的设计模式在Kotlin中的实现

2023-08-205.4k 阅读

单例模式在 Kotlin 中的实现

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

饿汉式单例

饿汉式单例在类加载时就创建实例,这种方式简单直接,并且线程安全。

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

在上述代码中,object关键字定义了一个单例对象。Singleton对象在第一次被使用时就会被初始化,并且 Kotlin 保证了这种初始化是线程安全的。使用时,直接通过Singleton.doSomething()调用即可。

懒汉式单例

懒汉式单例在第一次使用时才创建实例,实现懒加载。

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

这里通过companion object提供了一个getInstance方法来获取单例实例。在getInstance方法中,首先检查instance是否为null,如果是则创建实例。这种实现方式在多线程环境下是不安全的,如果多个线程同时调用getInstance,可能会创建多个实例。为了解决线程安全问题,可以使用@Synchronized关键字。

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

不过,在 Kotlin 中,还可以使用lazy委托属性来更优雅地实现懒汉式单例。

class LazySingleton private constructor() {
    companion object {
        val instance: LazySingleton by lazy { LazySingleton() }
    }
}

这里by lazy表示instance属性是懒加载的,只有在第一次访问instance时才会创建LazySingleton实例,并且这种方式是线程安全的。

工厂模式在 Kotlin 中的实现

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

简单工厂模式

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

abstract class Shape
class Circle : Shape()
class Rectangle : Shape()

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

在上述代码中,Shape是抽象产品类,CircleRectangle是具体产品类。ShapeFactory是工厂类,createShape方法根据传入的类型创建相应的形状实例。使用时:

val factory = ShapeFactory()
val circle = factory.createShape("circle")
val rectangle = factory.createShape("rectangle")

工厂方法模式

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

abstract class Shape
class Circle : Shape()
class Rectangle : Shape()

abstract class ShapeCreator {
    abstract fun createShape(): Shape
}

class CircleCreator : ShapeCreator() {
    override fun createShape(): Shape {
        return Circle()
    }
}

class RectangleCreator : ShapeCreator() {
    override fun createShape(): Shape {
        return Rectangle()
    }
}

这里ShapeCreator是抽象工厂类,定义了createShape抽象方法。CircleCreatorRectangleCreator是具体工厂类,分别实现createShape方法来创建具体的形状。使用时:

val circleCreator = CircleCreator()
val circle = circleCreator.createShape()

val rectangleCreator = RectangleCreator()
val rectangle = rectangleCreator.createShape()

抽象工厂模式

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

interface Shape
class Circle : Shape
class Rectangle : Shape

interface Color
class Red : Color
class Blue : Color

abstract class AbstractFactory {
    abstract fun createShape(): Shape
    abstract fun createColor(): Color
}

class ShapeColorFactory : AbstractFactory() {
    override fun createShape(): Shape {
        return Circle()
    }

    override fun createColor(): Color {
        return Red()
    }
}

在这个例子中,ShapeColor是两个不同类型的产品接口,AbstractFactory是抽象工厂类,定义了创建ShapeColor的抽象方法。ShapeColorFactory是具体工厂类,实现了创建具体ShapeColor的方法。使用时:

val factory = ShapeColorFactory()
val shape = factory.createShape()
val color = factory.createColor()

建造者模式在 Kotlin 中的实现

建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

class Computer {
    var cpu: String? = null
    var ram: String? = null
    var storage: String? = null

    override fun toString(): String {
        return "Computer(cpu=$cpu, ram=$ram, storage=$storage)"
    }
}

abstract class ComputerBuilder {
    protected val computer = Computer()
    abstract fun buildCPU()
    abstract fun buildRAM()
    abstract fun buildStorage()
    fun getComputer(): Computer {
        return computer
    }
}

class HighEndComputerBuilder : ComputerBuilder() {
    override fun buildCPU() {
        computer.cpu = "Intel Core i9"
    }

    override fun buildRAM() {
        computer.ram = "32GB DDR4"
    }

    override fun buildStorage() {
        computer.storage = "1TB SSD"
    }
}

class LowEndComputerBuilder : ComputerBuilder() {
    override fun buildCPU() {
        computer.cpu = "Intel Core i3"
    }

    override fun buildRAM() {
        computer.ram = "8GB DDR4"
    }

    override fun buildStorage() {
        computer.storage = "500GB HDD"
    }
}

class Director {
    private var computerBuilder: ComputerBuilder? = null

    fun setComputerBuilder(builder: ComputerBuilder) {
        computerBuilder = builder
    }

    fun constructComputer() {
        computerBuilder?.buildCPU()
        computerBuilder?.buildRAM()
        computerBuilder?.buildStorage()
    }

    fun getComputer(): Computer? {
        return computerBuilder?.getComputer()
    }
}

在上述代码中,Computer是复杂对象,ComputerBuilder是抽象建造者,HighEndComputerBuilderLowEndComputerBuilder是具体建造者,Director负责指导构建过程。使用时:

val director = Director()
val highEndBuilder = HighEndComputerBuilder()
director.setComputerBuilder(highEndBuilder)
director.constructComputer()
val highEndComputer = director.getComputer()

val lowEndBuilder = LowEndComputerBuilder()
director.setComputerBuilder(lowEndBuilder)
director.constructComputer()
val lowEndComputer = director.getComputer()

原型模式在 Kotlin 中的实现

原型模式通过复制现有对象来创建新对象,而不是通过实例化类。

interface Prototype {
    fun clone(): Prototype
}

class Rectangle(var width: Int, var height: Int) : Prototype {
    override fun clone(): Prototype {
        return Rectangle(width, height)
    }

    override fun toString(): String {
        return "Rectangle(width=$width, height=$height)"
    }
}

在这个例子中,Prototype是原型接口,Rectangle实现了该接口的clone方法来创建自身的副本。使用时:

val rectangle1 = Rectangle(10, 20)
val rectangle2 = rectangle1.clone() as Rectangle

适配器模式在 Kotlin 中的实现

适配器模式将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

类适配器

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接口来完成适配。使用时:

val adapter = ClassAdapter()
adapter.request()

对象适配器

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的实例,通过组合的方式实现适配。使用时:

val adaptee = Adaptee()
val adapter = ObjectAdapter(adaptee)
adapter.request()

桥接模式在 Kotlin 中的实现

桥接模式将抽象部分与它的实现部分分离,使它们都可以独立地变化。

interface Implementor {
    fun operation()
}

class ConcreteImplementorA : Implementor {
    override fun operation() {
        println("ConcreteImplementorA's operation.")
    }
}

class ConcreteImplementorB : Implementor {
    override fun operation() {
        println("ConcreteImplementorB's operation.")
    }
}

abstract class Abstraction {
    protected lateinit var implementor: Implementor
    fun setImplementor(implementor: Implementor) {
        this.implementor = implementor
    }
    abstract fun operation()
}

class RefinedAbstraction : Abstraction() {
    override fun operation() {
        implementor.operation()
    }
}

在上述代码中,Implementor是实现接口,ConcreteImplementorAConcreteImplementorB是具体实现类。Abstraction是抽象类,持有Implementor的引用,RefinedAbstraction是具体抽象类。使用时:

val abstraction = RefinedAbstraction()
val implementorA = ConcreteImplementorA()
abstraction.setImplementor(implementorA)
abstraction.operation()

val implementorB = ConcreteImplementorB()
abstraction.setImplementor(implementorB)
abstraction.operation()

组合模式在 Kotlin 中的实现

组合模式将对象组合成树形结构以表示“部分 - 整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

abstract class Component {
    protected val children: MutableList<Component> = mutableListOf()
    open fun add(component: Component) {
        children.add(component)
    }

    open fun remove(component: Component) {
        children.remove(component)
    }

    abstract fun operation()
}

class Leaf : Component() {
    override fun operation() {
        println("Leaf's operation.")
    }
}

class Composite : Component() {
    override fun operation() {
        println("Composite's operation.")
        children.forEach { it.operation() }
    }
}

在这个例子中,Component是抽象类,Leaf是叶子节点,Composite是组合节点。Composite可以包含其他Component(包括Leaf和其他Composite)。使用时:

val leaf1 = Leaf()
val leaf2 = Leaf()

val composite1 = Composite()
composite1.add(leaf1)

val composite2 = Composite()
composite2.add(leaf2)
composite2.add(composite1)

composite2.operation()

装饰器模式在 Kotlin 中的实现

装饰器模式动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式相比生成子类更为灵活。

interface Component {
    fun operation()
}

class ConcreteComponent : Component {
    override fun operation() {
        println("ConcreteComponent's operation.")
    }
}

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

class ConcreteDecoratorA(private val component: Component) : Decorator(component) {
    override fun operation() {
        super.operation()
        println("ConcreteDecoratorA's additional operation.")
    }
}

class ConcreteDecoratorB(private val component: Component) : Decorator(component) {
    override fun operation() {
        super.operation()
        println("ConcreteDecoratorB's additional operation.")
    }
}

在上述代码中,Component是抽象组件,ConcreteComponent是具体组件,Decorator是抽象装饰器,ConcreteDecoratorAConcreteDecoratorB是具体装饰器。使用时:

val component = ConcreteComponent()
val decoratorA = ConcreteDecoratorA(component)
val decoratorB = ConcreteDecoratorB(decoratorA)

decoratorB.operation()

外观模式在 Kotlin 中的实现

外观模式为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

class Subsystem1 {
    fun operation1() {
        println("Subsystem1's operation1.")
    }
}

class Subsystem2 {
    fun operation2() {
        println("Subsystem2's operation2.")
    }
}

class Facade {
    private val subsystem1 = Subsystem1()
    private val subsystem2 = Subsystem2()

    fun operation() {
        subsystem1.operation1()
        subsystem2.operation2()
    }
}

这里Subsystem1Subsystem2是子系统类,Facade是外观类,提供了一个统一的接口operation,封装了子系统的操作。使用时:

val facade = Facade()
facade.operation()

享元模式在 Kotlin 中的实现

享元模式运用共享技术有效地支持大量细粒度的对象。

interface Flyweight {
    fun operation()
}

class ConcreteFlyweight : Flyweight {
    private val intrinsicState: String

    constructor(intrinsicState: String) {
        this.intrinsicState = intrinsicState
    }

    override fun operation() {
        println("ConcreteFlyweight's operation with intrinsic state: $intrinsicState")
    }
}

class FlyweightFactory {
    private val flyweights: MutableMap<String, Flyweight> = mutableMapOf()

    fun getFlyweight(intrinsicState: String): Flyweight {
        return flyweights.getOrPut(intrinsicState) { ConcreteFlyweight(intrinsicState) }
    }
}

在上述代码中,Flyweight是抽象享元接口,ConcreteFlyweight是具体享元类,FlyweightFactory是享元工厂类,负责创建和管理享元对象。使用时:

val factory = FlyweightFactory()
val flyweight1 = factory.getFlyweight("state1")
val flyweight2 = factory.getFlyweight("state1")

flyweight1.operation()
flyweight2.operation()

代理模式在 Kotlin 中的实现

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

interface Subject {
    fun request()
}

class RealSubject : Subject {
    override fun request() {
        println("RealSubject's request.")
    }
}

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

这里Subject是抽象主题,RealSubject是真实主题,Proxy是代理类,在调用真实主题的方法前后可以进行额外的处理。使用时:

val realSubject = RealSubject()
val proxy = Proxy(realSubject)
proxy.request()

命令模式在 Kotlin 中的实现

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

interface Command {
    fun execute()
}

class Receiver {
    fun action() {
        println("Receiver's action.")
    }
}

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

class Invoker {
    private var command: Command? = null

    fun setCommand(command: Command) {
        this.command = command
    }

    fun executeCommand() {
        command?.execute()
    }
}

在上述代码中,Command是命令接口,Receiver是接收者,ConcreteCommand是具体命令类,Invoker是调用者。使用时:

val receiver = Receiver()
val command = ConcreteCommand(receiver)
val invoker = Invoker()
invoker.setCommand(command)
invoker.executeCommand()

观察者模式在 Kotlin 中的实现

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

interface Observer {
    fun update(subject: Subject)
}

interface Subject {
    fun attach(observer: Observer)
    fun detach(observer: Observer)
    fun notifyObservers()
}

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

    fun getState(): Int {
        return state
    }

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

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

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

    override fun notifyObservers() {
        observers.forEach { it.update(this) }
    }
}

class ConcreteObserver : Observer {
    private lateinit var subject: ConcreteSubject

    constructor(subject: ConcreteSubject) {
        this.subject = subject
        subject.attach(this)
    }

    override fun update(subject: Subject) {
        if (subject is ConcreteSubject) {
            println("ConcreteObserver updated with state: ${subject.getState()}")
        }
    }
}

在这个例子中,Observer是观察者接口,Subject是主题接口,ConcreteSubject是具体主题类,ConcreteObserver是具体观察者类。使用时:

val subject = ConcreteSubject()
val observer1 = ConcreteObserver(subject)
val observer2 = ConcreteObserver(subject)

subject.setState(10)

中介者模式在 Kotlin 中的实现

中介者模式用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

interface Mediator {
    fun send(message: String, colleague: Colleague)
}

abstract class Colleague {
    protected lateinit var mediator: Mediator
    constructor(mediator: Mediator) {
        this.mediator = mediator
    }
    abstract fun send(message: String)
    abstract fun receive(message: String)
}

class ConcreteMediator : Mediator {
    private val colleagues: MutableList<Colleague> = mutableListOf()

    fun addColleague(colleague: Colleague) {
        colleagues.add(colleague)
    }

    override fun send(message: String, colleague: Colleague) {
        colleagues.filter { it != colleague }.forEach { it.receive(message) }
    }
}

class ConcreteColleagueA : Colleague {
    constructor(mediator: Mediator) : super(mediator)

    override fun send(message: String) {
        mediator.send(message, this)
    }

    override fun receive(message: String) {
        println("ConcreteColleagueA received: $message")
    }
}

class ConcreteColleagueB : Colleague {
    constructor(mediator: Mediator) : super(mediator)

    override fun send(message: String) {
        mediator.send(message, this)
    }

    override fun receive(message: String) {
        println("ConcreteColleagueB received: $message")
    }
}

在上述代码中,Mediator是中介者接口,Colleague是同事抽象类,ConcreteMediator是具体中介者类,ConcreteColleagueAConcreteColleagueB是具体同事类。使用时:

val mediator = ConcreteMediator()
val colleagueA = ConcreteColleagueA(mediator)
val colleagueB = ConcreteColleagueB(mediator)

mediator.addColleague(colleagueA)
mediator.addColleague(colleagueB)

colleagueA.send("Hello from A")

迭代器模式在 Kotlin 中的实现

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

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

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

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

class ConcreteIterator<T>(private val items: List<T>) : Iterator<T> {
    private var position: Int = 0

    override fun hasNext(): Boolean {
        return position < items.size
    }

    override fun next(): T {
        if (!hasNext()) {
            throw NoSuchElementException()
        }
        val item = items[position]
        position++
        return item
    }
}

在这个例子中,Iterator是迭代器接口,Aggregate是聚合接口,ConcreteAggregate是具体聚合类,ConcreteIterator是具体迭代器类。使用时:

val numbers = listOf(1, 2, 3, 4, 5)
val aggregate = ConcreteAggregate(numbers)
val iterator = aggregate.createIterator()

while (iterator.hasNext()) {
    val number = iterator.next()
    println(number)
}

策略模式在 Kotlin 中的实现

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

interface Strategy {
    fun execute()
}

class ConcreteStrategyA : Strategy {
    override fun execute() {
        println("ConcreteStrategyA's execution.")
    }
}

class ConcreteStrategyB : Strategy {
    override fun execute() {
        println("ConcreteStrategyB's execution.")
    }
}

class Context(private var strategy: Strategy) {
    fun setStrategy(strategy: Strategy) {
        this.strategy = strategy
    }

    fun executeStrategy() {
        strategy.execute()
    }
}

在上述代码中,Strategy是策略接口,ConcreteStrategyAConcreteStrategyB是具体策略类,Context是上下文类,持有一个策略对象并调用其execute方法。使用时:

val context = Context(ConcreteStrategyA())
context.executeStrategy()

context.setStrategy(ConcreteStrategyB())
context.executeStrategy()

模板方法模式在 Kotlin 中的实现

模板方法模式定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

abstract class AbstractClass {
    fun templateMethod() {
        primitiveOperation1()
        primitiveOperation2()
        concreteOperation()
    }

    protected abstract fun primitiveOperation1()
    protected abstract fun primitiveOperation2()
    protected fun concreteOperation() {
        println("AbstractClass's concrete operation.")
    }
}

class ConcreteClass : AbstractClass() {
    override fun primitiveOperation1() {
        println("ConcreteClass's primitive operation1.")
    }

    override fun primitiveOperation2() {
        println("ConcreteClass's primitive operation2.")
    }
}

在这个例子中,AbstractClass是抽象类,定义了templateMethod模板方法,包含了算法的骨架,primitiveOperation1primitiveOperation2是抽象方法,由子类实现,concreteOperation是具体方法。ConcreteClass是具体子类,实现了抽象方法。使用时:

val concreteClass = ConcreteClass()
concreteClass.templateMethod()