Kotlin: 几种设计模式

创建型模式

原始模型

interface Computer {
	val cpu: String
}

class PC(override val cpu: String = "Core"): Computer
class Server(override val cpu: String = "Xeon"): Computer

enum class ComputerType {
	PC, Server
}

class ComputerFactory {
	fun produce(type: ComputerType): Computer {
		return when(type) {
			ComputerType.PC -> PC()
			ComputerType.Server -> Server()
		}
	}
}

>>> val comp = ComputerFactory().produce(ComputerType.PC)
>>> println(comp.cpu)
Core

使用单例代替工厂类

object ComputerFactory {
	fun produce(type: ComputerType): Computer {
		return when(type) {
			ComputerType.PC -> PC()
			ComputerType.Server -> Server()
		}
	}
}

>>> val comp = computerFactory.produce(ComputerType.PC)
>>> println(comp)
Core

invoke运算符重载

object ComputerFactory {
	operator fun invoke(type: ComputerType): Computer {
		return when(type) {
			ComputerType.PC -> PC()
			ComputerType.Server -> Server()
		}
	}
}

>>> val comp = computerFactory(ComputerType.PC)
>>> println(comp)
Core

伴生对象创建静态工厂方法

interface Computer {
	val cpu: String
	
	companion object {
		operator fun invoke(type: ComputerType): Computer {
			return when(type) {
				ComputerType.PC -> PC()
				ComputerType.Server -> Server()
			}
		}
	}
}

>>> val comp = Computer(ComputerType.PC)
>>> println(comp)
Core

具名伴生对象

interface Computer {
	val cpu: String
	
	companion object Factory {
		operator fun invoke(type: ComputerType): Computer {
			return whenn(type) {
				ComputerType.PC -> PC()
				ComputerType.Server -> Server()
			}
		}
	}
}

>>> val comp = Computer.Factory(ComputerType.PC)
>>> println(comp)
Core

扩展伴生对象方法

fun Computer.Companion.fromCPU(cpu: String): ComputerType? = when(cpu) {
	"Core" -> ComputerType.PC
	"Xeon" -> ComputerType.Server
}

fun Computer.Companion.Factory.fromCPU(cpu: String): ComputerType? = when(cpu) {
	"Core" -> ComputerType.PC
	"Xeon" -> ComputerType.Server
}

>>> val pc = Computer.fromCPU("Core")
>>> val server = Computer.Factory.fromCPU("Xeon")

抽象工厂模式
为创建一组相关或相互依赖的对象提供一个接口, 而且无需指定他们的具体类.

interface Computer
class Dell: Computer
class Asus: Computer
class Acer: Computer

class DellFactory: AbstrctFactory() {
	override fun produce() = Dell()
}

class AsusFactory: AbstractFactory() {
	override fun produce() = Asus()
}

class AcerFatory: AbstractFactory() {
	override fun produce() = Acer()
}

abstract class AbstractFactory {
	abstract fun produce(): Computer
	
	companion object {
		inline operator fun<reified T: Computer> invoke(): AbstractFactory = 
			when(T::class) {
				Dell::class -> DellFactory()
				Asus::class -> AsusFactory()
				Acer::class -> AcerFatory()
				else        -> throw IllegalArgumentException()
			}
	}
}

fun main(args:  Array<String>) {
	val dellFactory = AbstractFactory<Dell>()
	val dell = dellFactory.produce()
	println(dell)
}

用具名可选参数而不是构建者模式
本质上builder模式模拟类具名的可选参数,就像Ada和Python中的一样.

class Robot(
	val code: String,
	val battery: String? = null
	val height: Int? = null,
	val weight: Int? = null
) {
	init {
		require(weight == null || battery != null) {
			"Batter should be determined when setting weight."
		}
	}
}
>>> val robot1 = Robot(code = "007")
>>> val robot2 = Robot(code = "007", battery = "R6")
>>> val robot3 = Robot(code = "007", weight = 100)
java.lang.IllegalArgumentException: Batter should be determined when setting weight.

行为型模式

  • 观察者模式
    观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监听一个主题对象。这样以来,当被观察者状态发生改变时,需要通知相应的观察者,使这些观察者对象能够自动更新。

从java.util.Observable说起

import java.util.*

class StackUpdate: Observable() {
	val observers = mutableSetOf<Observer>();
	
	fun setStockChanged(price: Int) {
		this.Observers.forEach { it.update(this, price)}
	}
}

class StockDisplay: Observer {
	override fun update(o: Observable, price: Any) {
		jif (o is StockUpdate) {
			println("The latest stock price is ${price}.")
		}
	}
}

fun main(args: Array<String>) {
	val su = StockUpdate()
	val sd = StockDisplay()
	su.observers.add(sd)
	su.setStackChanged(100)
} 
// 运行结果
The latest stock price is 100.

Observable

import kotlin.properties.Delegates

interface StockUpdateListener {
	fun onRise(price: Int)
	fun onFall(price: Int)
}

class StockDisplay: StockUpdateListener {
	override fun onRise(price: Int) {
		println("The latest stock price has risen to ${price}.")
	}
	
	override fun onFall(price: Int) {
		println("The latest stock price has fell to ${price}.")
	}
}

class StockUpdate {
	var listeners = mutableSetOf<StockUpdateListener>()
	
	var price: Int by Delegates.observable(0) { _, old, new ->
		listeners.forEach {
			if (new > old) it.onRise(price) else it.onFall(price)
		}
	}
}

fun main(args: Array<String>) {
	val su = StockUpdate()
	val sd = StockDiaplay()
	su.listeners.add(sd)
	su.price = 100
	su.price = 98
}
// 运行结果
The latest stock price has risen to 100.
The latest stock price has fell to 98.

Vetoable

import kotlin.properties.Delegates

var value: Int by Delegates.vetoable(0) { prop, old, new ->
	new > 0
}

>>> value = 1
>>> println(value)
1
>>> value = -1
>>> println(value)
1

高阶函数简化策略模式、模版方法模式

原始策略模式

interface SwimStrategy {
	fun swim()
}

class Breaststroke: SwimStrategy {
	override fun swim() {
		println("I am breaststroking...")
	}
}

class Backstroke: SwimStrategy {
	override fun swim() {
		println("I am backstroke...")
	}
}

class Freestyle: SwimStrategy {
	override fun swim() {
		println("I am freestyling...")
	}
}

class Swimmer(val strategy: SwimStrategy) {
	fun swim() {
		strategy.swim()
	}
}

fun main(args: Array<String>) {
	val weekendShaw = Swimmer(Freestyle())
	weekendsShaw.swim()
	val weekdayShaw = Swimmer(Breaststroke())
	weekdayShaw.swim()
}
// 运行结果
I am freestyling...
I am breaststroking...

高阶函数抽象

fun breakstroke() {println("I am breaststroking...")}
fun backstroke() {println("I am backstroke...")}
fun freestyle() {println("I am freestyle...")}

class Swimmer(val swimming: () -> Unit) {
	fun swim() {
		swimming()
	}
}

fun main(args: Array<String>) {
	val weekendShaw = Swimmer(::freestyle)
	weekendShaw.swim()
	val weekdaysShaw = Swimmer(::breaststroke)
	weekdayShaw.swim()
}

模板方法模式:高阶函数代替继承
原始模板方法

abstract class CivicCenterTask {
	fun execute() {
		this.lineUp()
		this.askForHelp()
		this.evaluate()
	}
	
	private fun lineUp() {
		println("line up to take a number")
	}
	
	privaate fun evaluate() {
		println("evaluaten service attiude")
	}
	
	abstract fun askForHelp()
}

class PullSocialSecurity: CivicCenterTask {
	override fun askForHelp() {
		println("ask for pulling the social security")	
	}
}

class ApplyForCitizenCard: CiviCenterTask {
	override fun askForHelp() {
		println("apply for a citizen card")
	}
}

val pss = PullSocialSecurity()
>>> pss.execute()
line up to take a number
ask for pulling the social security
evaluaten service attitude

val afcc = ApplyForCitizenCard()
>>> afcc.execute()
line up to take a number
apply for a citizen card
evaluaten service attitude

高阶函数改造.

class CiviCenterTask {
	fun execute(askForHelp: () -> Unit) {
		this.lineUp()
		askForHelp()
		this.evaluate()
	}
	
	private lineUp() {
		println("line up to take a number")
	}
	
	private fun evalute() {
		println("evaluaten service attitude")
	}
}
	
fun pullSocialSecurity() {
	println("ask for pulling the social security")
}
	
fun applyForCitizenCard() {
	println("apply for citizen card")
}
	
var task1 = CivicCenterTask()
>>> task1.execute(::pullSocialSecurity)
line up to take a number
ask for pulling the social security
evaluaten service attitude
	
val task2 = CivicCenterTask()
>>> task2.execute(::applyForCityzenCard)
line up to take a number
apply for a citizen card
evaluaten service attitude

迭代器模式

  1. 实现Iterator接口
data class Book(val name: String)
class Bookcase(val books: List<Book>): Iterator<Book> {
	private val iterator: Iterator<Book>
	init {
		this.iterator = books.iterator()
	}
	
	override fun hasNext() = this.iterator.hasNext()
	override fun next() = this.iterator.next()
}

fun main(args: Array<String>) {
	val bookcase = Bookcase(
		listOf(Book("Dive into Kotlin"), Book("Thinking in Java"))
	)
	while(bookcase.hasNext()) {
		println("The book name is ${bookcase.next().name}")
	}
	for (book in bookcase) {
		println("The book name is ${book.name}")
	}
}
// 运行结果
The book name is Dive into Kotlin
The book name is Thinging in Java
The book name is Dive into Kotlin
The book name is Thinging in Java
  1. 重载iterator方法
data class Book(val name: String)
class Bookcase(val books: List<Book>) {
	operator fun iterator(): Iterator<Book> = this.books.iterator()
}

fun main(args: Array<String>) {
	for (book in bookcase) {
		println("The book name is ${book.name}")
	}
}
// 运行结果
The book name is Dive into Kotlin
The book name is Thinging in Java
  1. 通过扩展函数
data class Book(val name: String)
class Bookcase(val books: List<Book>){}

operator fun Bookcase.iterator(): Iterator<Book> = books.iterator()

// operator fun Bookcase.iterator(): Iterator<Book> = object: Iterator<Book> {
// 	val iterator = books.iterator()
// 	override fun hasNext() = iterator.hasNext()
// 	override fun next() = iterator.next()
// }

fun main(args: Array<String>) {
	for (book in bookcase) {
		println("The book name is ${book.name}")
	}
}
// 运行结果
The book name is Dive into Kotlin
The book name is Thinging in Java

用偏函数实现责任链模式
责任链模式的目的就是避免请求的发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

  1. 原始模型
data class ApplyEvent(val money: Int, val title: String)

interface ApplyHandler {
	val successor: ApplyHandler?
	fun handleEvent(event: AppleEvent)
}

class GroupLeader(override val successor: ApplyHandler?): ApplyHandler {
	override fun handleEvent(event: ApplyEvent) {
		when {
			event.money <= 100 -> println("Group Leader handled application: ${event.title}")
			else -> when(successor) {
				is ApplyHandler -> successor.handleEvent(event)
				else -> println("Group Leader: This application cannot be handdle.")
			}
		}
	}
}

class President(override val successor: ApplyHandler?): ApplyHandler {
	override fun handleEvent(event: ApplyEvent) {
		when {
			event.money <= 500 -> println("President handled application: ${event.title}")
			else -> when(successor) {
				is ApplyHandler -> successor.handleEvent(event)
				else -> println("Prisident: This application cannot be handdle")
			}
		}
	}
}

class College(override val successor: ApplyHnadler?): ApplyHandler {
	override fun handleEvent(event: ApplyEvent) {
		when {
			event.money > 1000 -> println("College: This application is refused.")
			else -> println("College handled application: ${event.title}")
		}
	}
}

fun main(args: Array<String>) {
	val college = College(null)
	val president = Predsident(college)
	val groupLeader = GroupLeader(president)
	
	groupLeader.handleEvent(ApplyEvent(10, "buy a pen"))
	groupLeader.handleEvent(ApplyEvent(200, "team building"))
	groupLeader.handleEvent(ApplyEvent(600, "hold a debate match"))
	groupLeader.handleEvent(ApplyEvent(1200, "annual meeting of the college"))
}
// 运行结果
Group Leader handled application: buy a pen.
President handled application: team building.
College handled application: hold a debate match.
College: This application is refused.

使用偏函数
偏函数是个数学中的概念,指的是定义域X中可能存在某些值在值域Y中没有对应的值。

开源库funKTionale实现了PartialFunction.

class PartialFunction<in P1, out R>(private val definedAt: (P1) -> Boolean, private val f: (P1) -> R) :(P1) -> R {
	override fun invoke(p1: P1): R {
		if (definedAt(P1)) {
			return f(p1)
		} else {
			throw IllegalArgumentException("Value: $(p1) isn't supported by this function")
		}
	}
	
	fun isDefinedAt(p1: P1) = definedAt(p1)
}

infix fun <P1, R> PartialFunction<P1, R>.OrElse(that: PartialFunction<P1, R>): PartialFunction<P1, R> {
	return PartialFunction({ this.isDefinedAt(it) || that.isDefinedAt(it) }) {
		when {
			this.isDefinedAt(it) -> this(it)
			else -> that(it)
		}
	}
}

data class ApplyEvent(val money: Int, val title: String)

val groupLeader = {
	val definedAt: (ApplyEvent) -> Boolean = { it.money <= 200 }
	val handler: (ApplyEvent) -> Unit = { println("Group Leader handled application: ${it.title}.")}
	PartialFunction(definedAt, handler)
}()

val president = {
	val definedAt: (ApplyEvent) -> Boolean =  { it.money <= 500}
	val handler: (ApplyEvent) -> Unit = { println("President handled application: ${it.title}.")}
	PartialFunction(definedAt, handler)
}()

val college = {
	val definedAt: (ApplyEvent) -> Boolean = { true }
	val handler: (ApplyEvent) -> Unit = {
		when {
			it.money > 1000 -> println("College: This application is refused.")
			else -> println("College handled application: ${it.title}")
		}
	}
	PartialFunction(definedAt, handler)
}()

val applyChain = groupLeader orElse president orElse college

>>> applyChain(ApplyEvent(600, "hold a debate match"))
College handled application: hold a debate match.

ADT 实现状态模式
状态模式允许一个对象在其内部状态改变时改变它的行为, 对象看起来似乎修改了它的类。

sealed class WaterMachineState(open val machine: WaterMachine) {
	fun turnHeating() {
		if (this !is Heating) {
			println("turn heating")
			machine.state = machine.heating
		} else {
			println("The state is already heating mode.")
		}
	}
	
	fun turnCooling() {
		if (this !is Cooling) {
			println("turn cooling")
			machine.state = machine.cooling
		} else {
			println("The state is already cooling mode.")
		}
	}
	
	fun turnOff() {
		if (this !is Off) {
			println("turn off")
			machine.state = machine.off
		} else {
			println("The state is already off.")
		}
	}
}

class Off(override val machine: WatterMachine): WatterMachineState(machine)

class Heating(override val machine: WatterMachine): WatterMachineState(machine)

class Cooling(override val machine: WatterMachine): 
WatterMachineState(machine)

class WaterMachine {
	var state: WaterMachineState
	val off = Off(this)
	val heating = Heating(this)
	val cooling = Cooling(this)
	
	init {
		this.state = off
	}
	
	fun turnHeating() {
		this.state.turnHeating()
	}
	
	fun turnCooling() {
		this.state.turnCooling()
	}
	
	fun turnOff() {
		this.state.turnOff()
	}
}

enum class Moment {
	EARLY_MORNING,
	DRINKING_WATER,
	INSTANCE_NOODLES,
	AFTER_WORK
}

fun waterMachineOps(machine: WaterMachine, moment: Moment) {
	when(moment) {
		Moment.EARLY_MORNING,
		Moment.DRINKING_WATER -> when(machine.state) {
			!is Cooling -> machine.turnCooling()
		}
		Moment.INSTANCE_NOODLES -> when(machine.state) {
			!is Heating -> machine.turnHeating()
		}
		Moment.AFTER_WORK -> when(machine.state) {
			!is OFF -> machine.turnOff()
		}
		else -> Unit
	}
}

fun main(args: Array<String>) {
	val machine = WaterMachine()
	waterMachineOps(machine, Moment.DRINKING_WATER)
	waterMachineOps(machine, Moment.INSTANCE_NOODLES)
	waterMachineOps(machine, Moment.DRINKING_WATER)
	waterMachineOps(machine, Moment.AFTER_WORk)
}
// 执行结果
turn cooling
turn heating
turn cooling
turn off

结构型模式

装饰模式: 使用委托减少样板代码
装饰模式就是在不必改变原类文件和使用继承的情况下, 动态地扩展一个对象的功能。该模式通过创建一个包装对象,来包裹真实的对象。

interface Macbook {
	fun getCost(): Int
	fun getDesc(): String
	fun getProdDate(): String
}

class MacBookPro: MacBook {
	override fun getCost() = 10000
	override fun getDesc() = "Macbook Pro"
	override fun getProdDate() = "Late 2011"
}

// 装饰类
class ProcessorUpgradeMacbookPro(val macbook: MacBook): MacBook by macbook {
	override fun getCost() = macbook.getCost() + 219
	override fun getDesc() = macbook.getDesc() + ", +1G Memory"
}

fun main(args: Array<String>) {
	val macBookPro = MacBookPro()
	val processorUpgradeMacbookPro = ProcessorUpgradeMacbookPro(macBookPro)
	println(processorUpgradeMacbookPro.getCost())
	println(processorUpgradeMacbookPro.getDesc())
}
// 运行结果
10219
Macbook Pro, +1G Memory

通过扩展代替装饰者

class Printer {
	fun drawline() {
		println("————————————————")
	}
	
	fun drawDottedLine() {
		println("----------------")
	}
	
	func drawStars() {
		println("****************")
	}
}

fun Printer.startDraw(decorated: Printer.() -> Unit) {
	println("+++ start drawing +++")
	this.decorated()
	println("+++ end drawing +++")
}

fun main(args: Array<String>) {
	Printer().run {
		startDraw {
			drawLine()
		}
		startDraw {
			drawDottedLine()
		}
		startDraw {
			drawStars()
		}
	}
}
// 运行结果
+++ start drawing +++
————————————————
+++ end drawing +++
+++ start drawing +++
----------------
+++ end drawing +++
+++ start drawing +++
****************
+++ end drawing +++
 Tg: Serialized binary TL-schema in vkext format(*.tlo) Mac OS包管理软件brew和port介绍 

Comments