面试复习题--kotlin的设计模式
Kotlin 以其简洁、安全、函数式特性,极大地改变了设计模式的实现方式。相比 Java,Kotlin 能以更少的代码实现相同的设计模式,甚至让某些模式变得“过时”或“内置”。
以下是针对 Kotlin 语言特性优化后的设计模式面试题,涵盖 常见模式、Kotlin 实现、对比 Java、高级技巧。
一、Kotlin 特性如何影响设计模式?
Kotlin 特性 | 对设计模式的影响 |
---|---|
数据类 data class | 替代 Builder 、Value Object 模式 |
单例 object | 内置线程安全单例,替代 Double-Checked Locking |
密封类 sealed class | 完美实现状态机、策略模式,替代枚举或复杂继承 |
扩展函数 extension function | 实现装饰器、适配器更简洁 |
高阶函数 & Lambda | 替代策略、命令、观察者等行为模式 |
委托 by 关键字 | 内置代理模式 |
空安全 ? | 减少 Null Object 模式的使用 |
作用域函数 let , apply , run , also | 简化构建、配置逻辑 |
二、高频 Kotlin 设计模式面试题
1. 如何在 Kotlin 中实现单例模式?有哪些方式?推荐哪种?
答:
方式一:object
(推荐 ✅)
kotlin
深色版本
object DatabaseManager {fun connect() = println("Connected")
}
// 使用
DatabaseManager.connect()
- ✅ 线程安全
- ✅ 懒加载(首次访问时初始化)
- ✅ 代码最简洁
- ✅ 防止反射攻击(Kotlin 1.4+)
方式二:object
+ @JvmStatic
(用于 Java 互操作)
kotlin
深色版本
object Logger {@JvmStaticfun log(msg: String) { ... }
}
方式三:静态内部类(Java 风格,不推荐 ❌)
kotlin
深色版本
class Preferences private constructor() {companion object {val instance by lazy { Preferences() }}
}
结论:优先使用
object
,它是 Kotlin 的“一等公民”。
2. 如何用 Kotlin 实现 Builder 模式?能否优化?
传统 Java Builder:
java
深色版本
User user = new User.Builder().name("Alice").age(25).build();
Kotlin 优化方案:
方案一:使用 默认参数 + 命名参数
kotlin
深色版本
data class User(val name: String,val age: Int = 0,val email: String? = null
)// 使用
val user = User(name = "Alice", age = 25)
- ✅ 最简洁
- ✅ 编译期安全
- ❌ 不适合大量可选参数(可读性下降)
方案二:使用 DSL 风格 Builder
kotlin
深色版本
class UserBuilder {var name: String = ""var age: Int = 0var email: String? = nullfun build() = User(name, age, email)
}fun user(init: UserBuilder.() -> Unit): User {return UserBuilder().apply(init).build()
}// 使用(DSL 风格)
val user = user {name = "Alice"age = 25email = "alice@example.com"
}
- ✅ 可读性强,适合复杂对象
- ✅ 类型安全
结论:优先用默认参数,复杂场景用 DSL Builder。
3. 如何用 Kotlin 实现策略模式?比 Java 好在哪?
Java 实现:
java
深色版本
interface Strategy { void execute(); }
class ConcreteStrategyA implements Strategy { ... }
class Context {private Strategy strategy;void setStrategy(Strategy s) { this.strategy = s; }
}
Kotlin 实现:
方案一:使用 高阶函数(推荐 ✅)
kotlin
深色版本
class PaymentProcessor {private var strategy: (amount: Double) -> Boolean = { false }fun setStrategy(strategy: (Double) -> Boolean) {this.strategy = strategy}fun process(amount: Double) = strategy(amount)
}// 使用
val processor = PaymentProcessor()
processor.setStrategy { amount ->println("Paying $amount via Credit Card")true
}
processor.process(100.0)
方案二:使用 密封类 + when
kotlin
深色版本
sealed class PaymentStrategy {object CreditCard : PaymentStrategy()object PayPal : PaymentStrategy()
}fun processPayment(strategy: PaymentStrategy, amount: Double) {when (strategy) {PaymentStrategy.CreditCard -> println("Credit Card: $amount")PaymentStrategy.PayPal -> println("PayPal: $amount")}
}
优势:
- ✅ 代码更短,无需定义接口/类
- ✅ 运行时性能更好(无对象创建)
- ✅ 支持 lambda 捕获上下文
4. 如何用 Kotlin 实现观察者模式?
Java 实现:接口 + 列表维护观察者。
Kotlin 优化方案:
方案一:使用 高阶函数 + MutableList
kotlin
深色版本
class DataStore {private val observers = mutableListOf<(String) -> Unit>()fun addObserver(observer: (String) -> Unit) {observers.add(observer)}fun notify(data: String) {observers.forEach { it(data) }}
}// 使用
val store = DataStore()
store.addObserver { println("Observer 1: $it") }
store.notify("Hello")
方案二:使用 Flow(推荐 ✅)
kotlin
深色版本
class DataStore {private val _data = MutableSharedFlow<String>()val data: Flow<String> = _data.asSharedFlow()suspend fun update(data: String) {_data.emit(data)}
}// 使用
store.data.collect { println(it) }
- ✅ 内置背压、线程切换、错误处理
- ✅ 支持
debounce
、distinctUntilChanged
等操作符 - ✅ 协程集成
结论:现代 Kotlin 项目推荐用
Flow
替代传统观察者模式。
5. 如何用 Kotlin 实现装饰器模式?
Java 实现:继承或组合 + 接口。
Kotlin 优化方案:
方案一:使用 扩展函数(推荐 ✅)
kotlin
深色版本
interface Notifier {fun send(message: String)
}class EmailNotifier : Notifier {override fun send(message: String) {println("Email: $message")}
}// 装饰:添加 SMS
fun Notifier.withSMS(): Notifier = object : Notifier by this {override fun send(message: String) {this@withSMS.send(message) // 调用原方法println("SMS: $message") // 新功能}
}// 使用
val notifier = EmailNotifier().withSMS()
notifier.send("Hello") // Email + SMS
方案二:使用 委托 by
kotlin
深色版本
class SMSDecorator(private val notifier: Notifier) : Notifier by notifier {override fun send(message: String) {notifier.send(message)println("SMS: $message")}
}
优势:Kotlin 的
by
和扩展函数让装饰器模式实现更简洁、类型安全。
6. 如何用 Kotlin 实现状态模式?
Java 实现:多态 + 状态类。
Kotlin 优化方案:密封类 + when
kotlin
深色版本
sealed class UiState {object Loading : UiState()data class Success(val data: List<String>) : UiState()data class Error(val message: String) : UiState()
}fun render(state: UiState) {when (state) {UiState.Loading -> showLoading()is UiState.Success -> showData(state.data)is UiState.Error -> showError(state.message)}
}
- ✅ 编译期 exhaustive check(
when
必须覆盖所有情况) - ✅ 数据封装安全
- ✅ 比继承树更清晰
结论:密封类是 Kotlin 实现状态模式的最佳方式。
7. Kotlin 中哪些设计模式变得“过时”了?
模式 | 为什么“过时” | Kotlin 替代方案 |
---|---|---|
Builder 模式 | 数据类 + 默认参数更简洁 | data class + 命名参数 |
Singleton | object 更安全简洁 | object |
Factory Method | companion object + when 更直接 | companion object create() |
Null Object | 空安全 ? 减少空指针 | 类型系统本身 |
Visitor | 密封类 + when 更安全 | sealed class + when |
三、高级面试题(结合协程、DSL)
1. 如何用 Kotlin 实现一个 DSL(领域特定语言)?
kotlin
深色版本
// 实现一个简单的 HTML DSL
fun html(init: HTML.() -> Unit): HTML {val html = HTML()html.init()return html
}class HTML {val body = Body()fun body(init: Body.() -> Unit) = body.init()
}class Body {val divs = mutableListOf<Div>()fun div(init: Div.() -> Unit) {divs += Div().apply(init)}
}class Div {var text: String = ""
}// 使用(像 HTML 一样写 Kotlin)
val result = html {body {div {text = "Hello"}}
}
应用场景:Gradle Kotlin DSL、Anko(已弃用)、Ktor 路由。
2. 如何用 Flow 实现发布-订阅模式?
kotlin
深色版本
class EventBus {private val _events = MutableSharedFlow<Event>()val events: Flow<Event> = _events.asSharedFlow()suspend fun post(event: Event) {_events.emit(event)}
}// 使用
eventBus.events.onEach { handleEvent(it) }.launchIn(scope)
- ✅ 支持背压
- ✅ 线程切换(
flowOn
) - ✅ 操作符丰富(
filter
,debounce
)
四、总结:Kotlin 设计模式面试要点
模式 | Kotlin 最佳实践 |
---|---|
Singleton | object |
Builder | data class + 默认参数 或 DSL |
Strategy | 高阶函数 (T) -> R |
Observer | Flow / SharedFlow |
State | sealed class + when |
Decorator | 扩展函数 或 by 委托 |
Factory | companion object + when |
Adapter | 扩展函数直接转换 |
💡 核心思想:用语言特性简化模式,而不是用模式模拟语言特性。
掌握这些 Kotlin 特有的实现方式,能让你在面试中脱颖而出,展现对语言深度的理解。