行为型模式
在软件工程中, 行为型设计模式是用来确认对象之间的公共的交流模式的。通过这样做,这些模式提高了实现这种交流的灵活性。
观察者模式
观察模式通常允许一个对象发布他的状态的变化。其他对象可以进行订阅,当其又任何变化时,其他对象都会马上收到通知。
举例:
interface TextChangedListener {
fun onTextChanged(newText: String)
}
class PrintingTextChangedListener : TextChangedListener {
override fun onTextChanged(newText: String) = println("Text is changed to: $newText")
}
class TextView {
var listener: TextChangedListener? = null
var text: String by Delegates.observable("") { prop, old, new ->
listener?.onTextChanged(new)
}
}
使用
val textView = TextView()
textView.listener = PrintingTextChangedListener()
textView.text = "Lorem ipsum"
textView.text = "dolor sit amet"
输出
Text is changed to: Lorem ipsum
Text is changed to: dolor sit amet
策略模式
策略模式一般用来创建一个可替换的算法簇,在运行时决定需要什么。
举例:
class Printer(val stringFormatterStrategy: (String) -> String) {
fun printString(string: String) = println(stringFormatterStrategy.invoke(string))
}
val lowerCaseFormatter: (String) -> String = { it.toLowerCase() }
val upperCaseFormatter = { it: String -> it.toUpperCase() }
使用
val lowerCasePrinter = Printer(lowerCaseFormatter)
lowerCasePrinter.printString("LOREM ipsum DOLOR sit amet")
val upperCasePrinter = Printer(upperCaseFormatter)
upperCasePrinter.printString("LOREM ipsum DOLOR sit amet")
val prefixPrinter = Printer({ "Prefix: " + it })
prefixPrinter.printString("LOREM ipsum DOLOR sit amet")
输出
lorem ipsum dolor sit amet
LOREM IPSUM DOLOR SIT AMET
Prefix: LOREM ipsum DOLOR sit amet
命令模式
命令模式通常用来表现一个请求,在一个命令对象包括产生的调用和所有它需要的参数。这个命令可能立即被执行,也有可能过一会再使用。
举例:
interface OrderCommand {
fun execute()
}
class OrderAddCommand(val id: Long) : OrderCommand {
override fun execute() = println("adding order with id: $id")
}
class OrderPayCommand(val id: Long) : OrderCommand {
override fun execute() = println("paying for order with id: $id")
}
class CommandProcessor {
private val queue = ArrayList<OrderCommand>()
fun addToQueue(orderCommand: OrderCommand): CommandProcessor
= apply { queue.add(orderCommand) }
fun processCommands(): CommandProcessor = apply {
queue.forEach { it.execute() }
queue.clear()
}
}
使用
CommandProcessor()
.addToQueue(OrderAddCommand(1L))
.addToQueue(OrderAddCommand(2L))
.addToQueue(OrderPayCommand(2L))
.addToQueue(OrderPayCommand(1L))
.processCommands()
输出
adding order with id: 1
adding order with id: 2
paying for order with id: 2
paying for order with id: 1
状态模式
状态模式一般用来在对象内部的状态发生改变时,更改这个对象的行为。这个模式允许在运行时显示的更改一个对象的类。
举例:
sealed class AuthorizationState {
class Unauthorized : AuthorizationState()
class Authorized(val userName: String) : AuthorizationState()
}
class AuthorizationPresenter {
private var state: AuthorizationState = Unauthorized()
fun loginUser(userLogin: String) {
state = Authorized(userLogin)
}
fun logoutUser() {
state = Unauthorized()
}
val isAuthorized: Boolean
get() {
when (state) {
is Authorized -> return true
else -> return false
}
}
val userLogin: String
get() {
when (state) {
is Authorized -> return (state as Authorized).userName
is Unauthorized -> return "Unknown"
}
}
override fun toString(): String {
return "User '$userLogin' is logged in: $isAuthorized"
}
}
使用
val authorization = AuthorizationPresenter()
authorization.loginUser("admin")
println(authorization)
authorization.logoutUser()
println(authorization)
输出
User 'admin' is logged in: true
User 'Unknown' is logged in: false
责任链模式
责任链模式通常用来处理多变的请求,每个请求可能交由不同的处理者进行处理。
举例:
interface MessageChain {
fun addLines(inputHeader: String): String
}
class AuthenticationHeader(val token: String?, var next: MessageChain? = null) : MessageChain {
override fun addLines(inputHeader: String): String {
token ?: throw IllegalStateException("Token should be not null")
return "$inputHeader Authorization: Bearer $token\n".let { next?.addLines(it) ?: it }
}
}
class ContentTypeHeader(val contentType: String, var next: MessageChain? = null) : MessageChain {
override fun addLines(inputHeader: String): String
= "$inputHeader ContentType: $contentType\n".let { next?.addLines(it) ?: it }
}
class BodyPayload(val body: String, var next: MessageChain? = null) : MessageChain {
override fun addLines(inputHeader: String): String
= "$inputHeader $body\n".let { next?.addLines(it) ?: it }
}
使用
val authenticationHeader = AuthenticationHeader("123456")
val contentTypeHeader = ContentTypeHeader("json")
val messageBody = BodyPayload("{\"username\"=\"dbacinski\"}")
val messageChainWithAuthorization = messageChainWithAuthorization(authenticationHeader, contentTypeHeader, messageBody)
val messageWithAuthentication = messageChainWithAuthorization.addLines("Message with Authentication:\n")
println(messageWithAuthentication)
fun messageChainWithAuthorization(authenticationHeader: AuthenticationHeader, contentTypeHeader: ContentTypeHeader, messageBody: BodyPayload): MessageChain {
authenticationHeader.next = contentTypeHeader
contentTypeHeader.next = messageBody
return authenticationHeader
}
输出
Message with Authentication:
Authorization: Bearer 123456
ContentType: json
{"username"="dbacinski"}
访问者模式
访问者模式通常用来将结构相对复杂的数据类从功能(根据它们所持有的数据来执行)中分离出来。
举例
interface ReportVisitable {
fun accept(visitor: ReportVisitor)
}
class FixedPriceContract(val costPerYear: Long) : ReportVisitable {
override fun accept(visitor: ReportVisitor) = visitor.visit(this)
}
class TimeAndMaterialsContract(val costPerHour: Long, val hours: Long) : ReportVisitable {
override fun accept(visitor: ReportVisitor) = visitor.visit(this)
}
class SupportContract(val costPerMonth: Long) : ReportVisitable {
override fun accept(visitor: ReportVisitor) = visitor.visit(this)
}
interface ReportVisitor {
fun visit(contract: FixedPriceContract)
fun visit(contract: TimeAndMaterialsContract)
fun visit(contract: SupportContract)
}
class MonthlyCostReportVisitor(var monthlyCost: Long = 0) : ReportVisitor {
override fun visit(contract: FixedPriceContract) {
monthlyCost += contract.costPerYear / 12
}
override fun visit(contract: TimeAndMaterialsContract) {
monthlyCost += contract.costPerHour * contract.hours
}
override fun visit(contract: SupportContract) {
monthlyCost += contract.costPerMonth
}
}
使用
val projectAlpha = FixedPriceContract(costPerYear = 10000)
val projectBeta = SupportContract(costPerMonth = 500)
val projectGamma = TimeAndMaterialsContract(hours = 150, costPerHour = 10)
val projectKappa = TimeAndMaterialsContract(hours = 50, costPerHour = 50)
val projects = arrayOf(projectAlpha, projectBeta, projectGamma, projectKappa)
val monthlyCostReportVisitor = MonthlyCostReportVisitor()
projects.forEach { it.accept(monthlyCostReportVisitor) }
println("Monthly cost: ${monthlyCostReportVisitor.monthlyCost}")
输出
Monthly cost: 5333
Github地址:Kotlin 设计模式
更多内容欢迎关注Kotlin学习网