Scala设计模式UML图例和代码实现实战 行为模式--责任链设计模式

16 篇文章 2 订阅
16 篇文章 0 订阅

示例类图
用于说明责任链设计模式的常见示例是关于应用程序中的事件处理,具体取决于它们是来自鼠标还是键盘操作。对于我们的类图和代码示例,让我们看看我们每天使用的其他东西 - ATM。他们如何以不同的音符组合返回正确的金额?答案当然是责任链。
我们将在这里提供两个图表 - 一个允许我们实现责任链模式的类,另一个将显示这些类如何一起用于构建我们的ATM。
首先,让我们分别看看我们的类:在上图中,我们有一个基类(在Scala中表示为特征),然后由不同的具体分配器进行扩展。每个分配器都有一个同一类的可选实例,这样我们就可以构建一个链。分配方法对于所有分配器是相同的,然后每个分配器在链中具有不同的量和不同的下一个元件。
当我们展示我们的ATM实施时,事情会变得更加清晰。可以在下图中看到:上图显示了我们ATM中的实际链。每当有人要钱时,自动柜员机将进入50英镑钞票的分配器,然后进入较低的分配器,依此类推,直到满足用户的要求为止。在下面的小节中,我们将逐步介绍我们的代码。
正如我们在前一节中提到的,分配方法对于扩展我们的分配器的每个人都是相同的,但链的数量和下一个元素将由扩展它的人定义。分配方法试图返回给定提名的尽可能多的注释;在此之后,如果仍有钱,它会将责任转移到下一个分配器。

在这里插入图片描述

在这里插入图片描述

下面的代码块显示了我们在前面代码中的实现,我们构建了将由我们的ATM类使用的分配器链。这里的顺序对于系统的正确运行非常重要。我们也做了一些健全检查。
以下应用程序使用我们的ATM类非常简单:这是一个等待用户输入然后使用ATM的交互式应用程序。让我们看看以下屏幕截图中的示例运行方式:正如您在代码中看到的那样,我们的ATM没有其他ATM具有的额外功能 - 检查笔记的可用性。然而,这是可以进一步扩展的功能。
Scala方式的责任链设计模式更仔细地查看代码和类图,可以看到装饰器设计模式的一些相似之处。这意味着在这里,我们可以使用相同的可堆叠特征,它们使用抽象覆盖构造。我们已经看到了这方面的一个例子,它不会为您提供任何新信息。但是,我们可以使用Scala编程语言的另一个功能来实现责任链设计模式 - 部分功能。
使用部分功能,我们不需要单独定义特定的分配器类。

当然,有不同的方法可以做到这一点 - 我们可以有一个抽象特征,然后实现部分函数(类似于原始示例)并且不指定dispenserAmount参数,或者我们可以有一个特征与此函数的不同实现,而不是传递dispenserAmount参数,依此类推。但是,这样做可以让我们以后模拟无数个不同音符的存在。

在前面的代码中,我们使用andThen方法链接了多个部分函数,​​最后,我们使用它们的结果作为方法。
根据开发人员想要创建的链,他们可以使用部分函数的orElse或andThen方法。前者对单个处理程序有用,后者对链接有用。

完整代码如下:

case class Money(amount: Int)

trait Dispenser {
val amount: Int
val next: Option[Dispenser]

def dispense(money: Money): Unit = {
if (money.amount >= amount) {
val notes = money.amount / amount
val left = money.amount % amount
System.out.println(s"Dispensing $notes note/s of $amount.")
if (left > 0) next.map(.dispense(Money(left)))
} else {
next.foreach(
.dispense(money))
}
}
}

class Dispenser50(val next: Option[Dispenser]) extends Dispenser {
override val amount = 50
}

class Dispenser20(val next: Option[Dispenser]) extends Dispenser {
override val amount: Int = 20
}

class Dispenser10(val next: Option[Dispenser]) extends Dispenser {
override val amount: Int = 10
}

class Dispenser5(val next: Option[Dispenser]) extends Dispenser {
override val amount: Int = 5
}

trait PartialFunctionDispenser {

def dispense(dispenserAmount: Int): PartialFunction[Money, Money] = {
case Money(amount) if amount >= dispenserAmount =>
val notes = amount / dispenserAmount
val left = amount % dispenserAmount
System.out.println(s"Dispensing $notes note/s of $dispenserAmount.")
Money(left)
case m @ Money(amount) =>
m
}
}

import scala.io.Source

class ATM {
val dispenser: Dispenser = {
val d1 = new Dispenser5(None)
val d2 = new Dispenser10(Some(d1))
val d3 = new Dispenser20(Some(d2))
new Dispenser50(Some(d3))
}

def requestMoney(money: Money): Unit = {
if (money.amount % 5 != 0) {
System.err.println(“The smallest nominal is 5 and we cannot satisfy your request.”)
} else {
dispenser.dispense(money)
}
}
}

class PartialFunctionATM extends PartialFunctionDispenser {

val dispenser = dispense(50).andThen(dispense(20)).andThen(dispense(10)).andThen(dispense(5))

def requestMoney(money: Money): Unit = {
if (money.amount % 5 != 0) {
System.err.println(“The smallest nominal is 5 and we cannot satisfy your request.”)
} else {
dispenser(money)
}
}
}

object ATMExample {
def main(args: Array[String]): Unit = {
val atm = new ATM
printHelp()
Source.stdin.getLines().foreach {
case line =>
processLine(line, atm)
}
}

def printHelp(): Unit = {
System.out.println("Usage: ")
System.out.println(“1. Write an amount to withdraw…”)
System.out.println(“2. Write EXIT to quit the application.”)
}

def processLine(line: String, atm: ATM): Unit = {
line match {
case “EXIT” =>
System.out.println(“Bye!”)
System.exit(0)
case l =>
try {
atm.requestMoney(Money(l.toInt))
System.out.println(“Thanks!”)
} catch {
case _: Throwable =>
System.err.println(s"Invalid input: $l.")
printHelp()
}

}

}
}

object PartialFunctionATMExample {
def main(args: Array[String]): Unit = {
val atm = new PartialFunctionATM
printHelp()
Source.stdin.getLines().foreach {
case line =>
processLine(line, atm)
}
}

def printHelp(): Unit = {
System.out.println("Usage: ")
System.out.println(“1. Write an amount to withdraw…”)
System.out.println(“2. Write EXIT to quit the application.”)
}

def processLine(line: String, atm: PartialFunctionATM): Unit = {
line match {
case “EXIT” =>
System.out.println(“Bye!”)
System.exit(0)
case l =>
try {
atm.requestMoney(Money(l.toInt))
System.out.println(“Thanks!”)
} catch {
case _: Throwable =>
System.err.println(s"Invalid input: $l.")
printHelp()
}

}

}
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值