Scala设计模式UML图例和代码实现实战 行为模式--观察者设计模式

 

 

示例类图对于类图,让我们关注以下示例 - 我们有一个包含帖子的网站,人们可以订阅在添加新评论时收到通知。下图显示了如何使用观察者设计模式表示此类内容:Post类是我们的可观察对象,它具有User类型的观察者,每当帖子发生更改时(在我们的情况下,添加注释时)都会通知。
请注意,前面的场景只是一个示例。实际上,订阅可以在数据库中完成,人们将收到电子邮件通知。但是,如果我们在您访问网站时谈论某种通知,则此示例有效。
示例中的观察者模式可能并且可能应该使用Akka和actor在Scala中使用反应式编程替换。这样,我们可以实现更好的可伸缩性并实现适当的异步发布 - 订阅系统。
在下面的小节中,我们将看一下代表上图的代码。
代码示例现在,让我们浏览代表上图的所有代码。首先,让我们看一下Observer接口。我们决定把它作为一个可以混合在任何类中的特性:

trait Observer [T] {def handleUpdate(subject:T)}

这非常简单。接下来,我们将看一下Observable类。它是一个特性,也可以混合在一起并且可以使类可观察:

trait Observable [T] {this:T => private val observers = ListBuffer [Observer [T]]()def addObserver(observer:Observer [T]) :单位= {观察员。 = :( observer)} d ef notifyObservers():Unit = {observers.foreach(_。handleUpdate(this))}}

 

在上面的代码中,我们使用了自我类型以确保我们限制了混合了可观察特征。这可以确保参数化类型与我们混合它的对象的类型相同。
我们的Observer接口的实现将是我们的User类。它有以下代码:

 

 

它就像实现一个方法一样简单,并使用已更改的Post主题执行某些操作。
Comment类只是一个简单的模型类,它没有什么特别之处:case class Comment(user:User,text:String)Post类将是Observable。 对于添加的每个注释,此类将通知所有已注册的观察者。 代码如下:case class Post(user:User,text:String)extends Observable [Post] {val comments = ListBuffer [Comment]()def addComment(comment:Comment):Unit = {comments。 = :( comment)notifyObservers()}}前面的所有代码片段都实现了我们的观察者设计模式。 有趣的是,在一个例子中看到它是如何工作的。 下面的代码块有一个如何一起使用我们的类的示例:

 

abstract class Element(text: String) {
  def accept(visitor: Element => Unit): Unit = {
    visitor(this)
  }
}

case class Title(text: String) extends Element(text)
case class Text(text: String) extends Element(text)
case class Hyperlink(text: String, val url: String) extends Element(text)

class Document(parts: List[Element]) {

  def accept(visitor: Element => Unit): Unit = {
    parts.foreach(p => p.accept(visitor))
  }
}

 

object VisitorExample {
  val line = System.getProperty("line.separator")
  
  def htmlExporterVisitor(builder: StringBuilder): Element => Unit = {
    case Title(text) =>
      builder.append(s"<h1>${text}</h1>").append(line)
    case Text(text) =>
      builder.append(s"<p>${text}</p>").append(line)
    case Hyperlink(text, url) =>
      builder.append(s"""<a href=\"${url}\">${text}</a>""").append(line)
  }
  
  def plainTextExporterVisitor(builder: StringBuilder): Element => Unit = {
    case Title(text) =>
      builder.append(text).append(line)
    case Text(text) =>
      builder.append(text).append(line)
    case Hyperlink(text, url) =>
      builder.append(s"${text} (${url})").append(line)
  }
  
  def main(args: Array[String]): Unit = {
    val document = new Document(
      List(
        Title("The Visitor Pattern Example"),
        Text("The visitor pattern helps us add extra functionality without changing the classes."),
        Hyperlink("Go check it online!", "https://www.google.com/"),
        Text("Thanks!")
      )
    )

    val html = new StringBuilder
    System.out.println(s"Export to html:")
    document.accept(htmlExporterVisitor(html))
    System.out.println(html.toString())

    val plain = new StringBuilder
    System.out.println(s"Export to plain:")
    document.accept(plainTextExporterVisitor(plain))
    System.out.println(plain.toString())
  }
}

 

正如您在前面的屏幕截图中所看到的,观察者设计模式非常容易实现。正如我们前面提到的,更好的方法是使用反应式编程,以使异步和更具可伸缩性。它也将更具功能性。我们将在本书的后续章节中看到如何使用Akka完成此操作的示例。
它有什么好处观察者设计模式易于实现,并允许我们在运行时添加新观察者或删除旧观察者。它有助于解耦逻辑和通信,这使得一些高质量的类只有一个责任。
在使用Scala进行函数式编程时,人们可能更喜欢使用Akka并创建一个发布 - 订阅设计。
此外,在观察者设计模式中,对象引用保存在观察者的主体集合中,这可能在应用程序或主题对象的生命周期中导致内存泄漏或不必要的分配。最后,与任何其他设计模式一样,只应在必要时使用观察者设计模式。否则,我们可能会因为没有充分理由而使我们的应用程序复杂化。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心自由天使

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值