欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 会展 > 《Kotlin核心编程》下篇

《Kotlin核心编程》下篇

2025/1/30 10:54:05 来源:https://blog.csdn.net/weixin_38244174/article/details/145348662  浏览:    关键词:《Kotlin核心编程》下篇

设计模式

设计模式分类

创建型设计模式:

  • 概念:创建型设计模式主要用于对象的创建过程,比如对象的实例化、创建对象的方式和时机等,它关注的是如何将对象的创建和使用分离,使得代码在创建对象时更加灵活、可维护和可扩展。

  • 特点:封装对象创建过程;提高灵活性;便于代码复用。

  • 常见模式:单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式。

结构型设计模式:

  • 概念:结构型设计模式主要用于处理类或对象的组合结构,它关注的是如何将类或对象组合成更大的结构,以及如何在这些结构中实现功能的扩展和优化。

  • 特点:组合对象结构;增强功能;提高可维护性。

  • 常见模式:代理模式、适配器模式、桥接模式、装饰模式、外观模式、享元模式、组合模式。

行为型设计模式:

  • 概念:行为型设计模式主要用于处理对象之间的交互和职责分配,它关注的是对象之间如何进行通信、协作以及如何分配职责,以实现系统的功能和行为。

  • 特点:对象间交互;职责分配;提高可扩展性。

  • 常见模式:策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

工厂模式

工厂模式是一种创建对象的设计模式,它将对象的创建和使用分离。通过使用工厂类来创建对象,而不是在客户端代码中直接实例化,这样可以降低代码的耦合度,提高可维护性和可扩展性。例如,有一个Shape接口及其实现类CircleRectangle,可以创建一个ShapeFactory工厂类:

interface Shape {fun draw()
}class Circle : Shape {override fun draw() {println("Drawing a circle")}
}class Rectangle : Shape {override fun draw() {println("Drawing a rectangle")}
}class ShapeFactory {fun createShape(shapeType: String): Shape? {return when (shapeType) {"CIRCLE" -> Circle()"RECTANGLE" -> Rectangle()else -> null}}
}

使用示例:

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

内联函数简化抽象工厂

内联函数在编译时会将函数体直接插入到调用处,减少函数调用开销。在抽象工厂模式中,使用内联函数可以简化代码结构。例如,定义一个内联的抽象工厂函数,用于创建不同类型的数据库连接:

interface DatabaseConnection {fun connect()
}class MySQLConnection : DatabaseConnection {override fun connect() {println("Connecting to MySQL database")}
}class PostgreSQLConnection : DatabaseConnection {override fun connect() {println("Connecting to PostgreSQL database")}
}inline fun createDatabaseConnection(type: String): DatabaseConnection = when (type) {"MYSQL" -> MySQLConnection()"POSTGRESQL" -> PostgreSQLConnection()else -> throw IllegalArgumentException("Unsupported database type")
}

使用示例:

fun main() {val connection = createDatabaseConnection("MYSQL")connection.connect()
}

构建者模式

构建者模式用于创建复杂对象,将对象的构建过程和表示分离,使得同样的构建过程可以创建不同的表示。比如创建一个Computer类,其配置较为复杂:

class Computer(val cpu: String,val ram: String,val storage: String
)class ComputerBuilder {private var cpu: String = ""private var ram: String = ""private var storage: String = ""fun setCpu(cpu: String): ComputerBuilder {this.cpu = cpureturn this}fun setRam(ram: String): ComputerBuilder {this.ram = ramreturn this}fun setStorage(storage: String): ComputerBuilder {this.storage = storagereturn this}fun build(): Computer {return Computer(cpu, ram, storage)}
}

使用示例:

fun main() {val computer = ComputerBuilder().setCpu("Intel i7").setRam("16GB").setStorage("1TB SSD").build()println("Computer configured: CPU - ${computer.cpu}, RAM - ${computer.ram}, Storage - ${computer.storage}")
}

观察者模式

观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新 。在 Kotlin 中可以通过委托来实现观察者模式。假设有一个被观察的Subject类和多个Observer

interface Observer {fun update(message: String)
}class Subject {private val observers: MutableList<Observer> = mutableListOf()fun registerObserver(observer: Observer) {observers.add(observer)}fun removeObserver(observer: Observer) {observers.remove(observer)}fun notifyObservers(message: String) {observers.forEach { it.update(message) }}
}class ConcreteObserver : Observer {override fun update(message: String) {println("Observer received message: $message")}
}

使用示例:

fun main() {val subject = Subject()val observer = ConcreteObserver()subject.registerObserver(observer)subject.notifyObservers("Something has changed!")
}

高阶函数简化设计模式

高阶函数可以以函数作为参数或返回值,利用这一特性可以简化一些设计模式的实现。例如策略模式,它定义了一系列算法,将每个算法都封装起来,并且使它们可以相互替换。通过高阶函数实现一个简单的计算策略模式:

typealias MathOperation = (Int, Int) -> Intfun calculate(a: Int, b: Int, operation: MathOperation): Int {return operation(a, b)
}fun main() {val add: MathOperation = { x, y -> x + y }val subtract: MathOperation = { x, y -> x - y }val result1 = calculate(5, 3, add)val result2 = calculate(5, 3, subtract)println("Addition result: $result1")println("Subtraction result: $result2")
}

重载 iterator 方法、责任链模式、ADT 实现状态模式

  • 重载 iterator 方法:在 Kotlin 中,通过重载iterator方法可以使自定义类支持迭代操作。例如,创建一个简单的自定义集合类:

class MyList<T>(private val elements: Array<T>) : Iterable<T> {override fun iterator(): Iterator<T> = object : Iterator<T> {private var index = 0override fun hasNext(): Boolean = index < elements.sizeoverride fun next(): T = elements[index++]}
}fun main() {val myList = MyList(arrayOf(1, 2, 3))for (element in myList) {println(element)}
}
  • 责任链模式:责任链模式使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。例如,处理请假审批流程:

abstract class Approver {protected var successor: Approver? = nullfun setSuccessor(successor: Approver) {this.successor = successor}abstract fun processRequest(request: Int)
}class TeamLead : Approver() {override fun processRequest(request: Int) {if (request <= 2) {println("Team lead approved the leave for $request days")} else {successor?.processRequest(request)}}
}class Manager : Approver() {override fun processRequest(request: Int) {if (request <= 5) {println("Manager approved the leave for $request days")} else {successor?.processRequest(request)}}
}class Director : Approver() {override fun processRequest(request: Int) {if (request <= 10) {println("Director approved the leave for $request days")} else {println("Request needs further discussion")}}
}//使用示例
fun main() {val teamLead = TeamLead()val manager = Manager()val director = Director()teamLead.setSuccessor(manager)manager.setSuccessor(director)teamLead.processRequest(3)
}
  • ADT 实现状态模式:代数数据类型(ADT)可以很好地实现状态模式。状态模式允许对象在内部状态改变时改变它的行为。例如,实现一个简单的电梯状态管理:

sealed class ElevatorState
class Idle : ElevatorState()
class MovingUp : ElevatorState()
class MovingDown : ElevatorState()class Elevator {private var state: ElevatorState = Idle()fun moveUp() {when (state) {is Idle -> {state = MovingUp()println("Elevator is moving up")}is MovingDown -> {state = MovingUp()println("Elevator stopped and is moving up")}else -> println("Elevator is already moving up")}}fun moveDown() {when (state) {is Idle -> {state = MovingDown()println("Elevator is moving down")}is MovingUp -> {state = MovingDown()println("Elevator stopped and is moving down")}else -> println("Elevator is already moving down")}}
}//使用示例
fun main() {val elevator = Elevator()elevator.moveUp()elevator.moveDown()}
}

装饰模式

装饰模式动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式相比生成子类更为灵活。例如,有一个Coffee接口及其实现类SimpleCoffee,可以通过装饰类为咖啡添加不同配料:

interface Coffee {fun getCost(): Doublefun getDescription(): String
}class SimpleCoffee : Coffee {override fun getCost(): Double = 1.0override fun getDescription(): String = "Simple coffee"
}class MilkDecorator(private val coffee: Coffee) : Coffee {override fun getCost(): Double = coffee.getCost() + 0.5override fun getDescription(): String = "${coffee.getDescription()}, with milk"
}class SugarDecorator(private val coffee: Coffee) : Coffee {override fun getCost(): Double = coffee.getCost() + 0.2override fun getDescription(): String = "${coffee.getDescription()}, with sugar"
}//使用示例
fun main() {val simpleCoffee = SimpleCoffee()val coffeeWithMilk = MilkDecorator(simpleCoffee)val coffeeWithMilkAndSugar = SugarDecorator(coffeeWithMilk)println("${coffeeWithMilkAndSugar.getDescription()}: ${coffeeWithMilkAndSugar.getCost()}")
}

函数式编程

函数式语言

  • 函数是一等公民:在 Kotlin 中,函数可以像普通数据类型一样进行操作,例如作为参数传递给其他函数、作为函数的返回值,或者存储在变量中。

//1.第一个示例:
//定义一个函数并赋值给变量
val add: (Int, Int) -> Int = { a, b -> a + b }
// 使用变量调用函数
val result = add(3, 5)
println(result)//2.第二个示例:函数作为参数传递给其他函数
// 定义一个接受函数作为参数的高阶函数
fun operateOnNumbers(a: Int, b: Int, operation: (Int, Int) -> Int): Int {return operation(a, b)
}
// 定义一个简单的乘法函数
val multiply: (Int, Int) -> Int = { a, b -> a * b }
// 将乘法函数作为参数传递给高阶函数
val multiplyResult = operateOnNumbers(4, 6, multiply)
println(multiplyResult)//3.第三个示例:函数作为返回值
// 定义一个根据条件返回不同函数的高阶函数
fun getOperation(shouldAdd: Boolean): (Int, Int) -> Int {return if (shouldAdd) {{ a, b -> a + b }} else {{ a, b -> a - b }}
}
// 根据条件获取函数并调用
val operation = getOperation(true)
val operationResult = operation(10, 5)
println(operationResult)
  • 声明式编程风格:在 Kotlin 中,使用集合操作函数体现声明式编程风格,只需要声明对数据的操作,而不需要关心具体的实现细节。

val numbers = listOf(1, 2, 3, 4, 5)
// 筛选出偶数并计算平方
val squaredEvenNumbers = numbers.filter { it % 2 == 0 }.map { it * it }
println(squaredEvenNumbers)

引用透明性和副作用

  • 引用透明性:满足引用透明性的函数,给定相同的输入,总是返回相同的输出,并且不会产生任何可观察的副作用。

// 一个具有引用透明性的纯函数
fun square(x: Int): Int = x * x
// 无论何时调用,结果都相同
val result1 = square(5)
val result2 = square(5)
println(result1)
println(result2)
  • 副作用:副作用是指函数在执行过程中,除了返回值之外,对外部状态产生的影响,如修改全局变量、进行 I/O 操作等。

// 定义一个全局变量
var globalVar = 0
// 一个具有副作用的函数,修改全局变量
fun incrementGlobal() {globalVar++
}
// 调用具有副作用的函数
incrementGlobal()
println(globalVar)

纯函数和局部可变性

  • 纯函数:纯函数是满足引用透明性的函数,不依赖外部状态,只根据输入参数返回确定的输出。

// 纯函数示例,计算两个数的商
fun divide(a: Int, b: Int): Double {require(b!= 0) { "除数不能为零" }return a.toDouble() / b
}
// 调用纯函数
val divisionResult = divide(10, 2)
println(divisionResult)
  • 局部可变性:虽然函数式编程强调不可变性,但在某些情况下,在局部范围内使用可变变量可以提高效率或实现特定算法。

// 在函数内部使用可变变量实现累加
fun sumList(list: List<Int>): Int {var result = 0list.forEach { result += it }return result
}
val numbersList = listOf(1, 2, 3, 4, 5)
val sum = sumList(numbersList)
println(sum)

异步和并发

基本概念

  • 异步:程序在执行过程中,某些操作无需等待当前任务完成,就能继续执行后续代码,不会阻塞主线程,提升用户体验。比如在 Android 应用中,进行网络请求时采用异步方式,主线程不会因等待数据而卡顿,用户可继续操作界面。在 Kotlin 中,异步主要通过协程来实现。协程是一种轻量级的线程模型,它基于挂起函数(suspend function)来暂停和恢复执行。挂起函数可以暂停当前协程的执行,并将控制权交回给调用者,而不会阻塞底层线程。这样,其他协程就可以在同一线程上运行,从而实现了异步执行。

  • 并发:指在同一时间段内,多个任务看似同时执行。在单核 CPU 系统里,通过任务快速切换模拟同时执行;多核 CPU 系统则能真正并行执行任务,充分利用系统资源,提高程序运行效率。

核心技术

  • 协程

    • 挂起函数:以 suspend 关键字修饰,可暂停执行并将控制权交回调用者,不阻塞线程。常用于异步操作,如网络请求、文件读取等。例如:suspend fun readFile() : String,函数内部执行文件读取时可暂停,等待数据读取完毕再恢复。

    • 协程构建器:

      • launch:启动新协程并立即执行,无返回值。主要用于执行独立的异步任务,如更新 UI、记录日志等。例如:launch { doSomeBackgroundWork() }

      • async:启动协程并返回 Deferred 对象,通过 await 方法获取协程执行结果。适用于需要异步计算并获取结果的场景,如多个数据的并行计算。例如:val deferredResult = async { calculateValue() }; val result = deferredResult.await()

    • 协程上下文与调度器:协程上下文包含协程运行的环境信息,调度器是其中关键部分,决定协程执行的线程或线程池。

      • Dispatchers.Main:用于 Android 主线程,更新 UI 等操作必须在此调度器执行。

      • Dispatchers.IO:适合 I/O 密集型任务,如文件读写、网络请求,它使用一个线程池来处理这些任务。

      • Dispatchers.Default:适用于 CPU 密集型任务,利用共享线程池执行,充分利用多核 CPU 性能。

  • 线程

    • 创建方式:可通过继承 Thread 类或实现 Runnable 接口创建线程。不过,Kotlin 中协程提供了更简洁、高效的异步处理方式,线程使用相对较少。例如继承 Thread 类:

class MyThread : Thread() {override fun run() {// 线程执行逻辑}
}
val myThread = MyThread()
myThread.start()
  • 线程安全:多线程访问共享资源时,可能引发数据不一致问题。解决方法有:

    • 同步块:使用 synchronized 关键字包裹共享资源访问代码,保证同一时刻只有一个线程能访问。

    • 锁机制:ReentrantLock 等锁类提供更灵活的同步控制。使用时先获取锁,操作完成后释放锁。

val lock = ReentrantLock()
lock.lock()
try {// 访问共享资源的代码
} finally {lock.unlock()
}

实际应用

  • 网络请求:结合协程与网络框架(如 OkHttp),实现异步网络请求。在 Dispatchers.IO 调度器执行请求,获取数据后切换到 Dispatchers.Main 更新 UI。例如:

    • 当按钮被点击时,使用 CoroutineScope(Dispatchers.Main).launch 在主线程启动一个协程。

    • 在协程中调用 fetchData 函数进行网络请求,fetchData 函数使用 withContext(Dispatchers.IO) 将网络请求操作切换到 Dispatchers.IO 调度器执行,避免阻塞主线程。

    • 当网络请求完成后,将结果赋值给 resultTextViewtext 属性,由于协程在主线程启动,所以可以直接更新 UI。

class MainActivity : AppCompatActivity() {private lateinit var fetchDataButton: Buttonprivate lateinit var resultTextView: TextViewoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)fetchDataButton = findViewById(R.id.fetchDataButton)resultTextView = findViewById(R.id.resultTextView)fetchDataButton.setOnClickListener {// 在主线程启动协程CoroutineScope(Dispatchers.Main).launch {try {// 调用 fetchData 函数进行网络请求val result = fetchData()// 在主线程更新 UIresultTextView.text = result} catch (e: Exception) {resultTextView.text = "Error: ${e.message}"}}}}private suspend fun fetchData(): String {return withContext(Dispatchers.IO) {val client = OkHttpClient()val request = Request.Builder().url("https://jsonplaceholder.typicode.com/todos/1").build()try {val response = client.newCall(request).execute()response.body?.string() ?: ""} catch (e: IOException) {"Network error: ${e.message}"}}}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com