当前位置: 首页 > 知识库问答 >
问题:

哪种GOF设计模式具有完全不同的实现(java与Scala)

宦正诚
2023-03-14

最近我读到以下问题:

在Scala中有使用Visitor模式的用例吗?我应该每次在Java中使用访问者模式时都在Scala中使用模式匹配吗?

造物模式

  • 抽象工厂
  • 生成器
  • 工厂方法
  • 原型
  • 单例:直接创建对象(scala)

结构模式

    null
    null

共有1个答案

周锐
2023-03-14

对于几乎所有这些,都有Scala替代方案,覆盖了这些模式的部分但不是全部用例。当然,所有这些都是IMO,但是:

Scala可以用泛型类型比Java更优雅地实现这一点,但大意是相同的。在Scala中,模式最简单的实现如下:

trait Status
trait Done extends Status
trait Need extends Status

case class Built(a: Int, b: String) {}
class Builder[A <: Status, B <: Status] private () {
  private var built = Built(0,"")
  def setA(a0: Int) = { built = built.copy(a = a0); this.asInstanceOf[Builder[Done,B]] }
  def setB(b0: String) = { built = built.copy(b = b0); this.asInstanceOf[Builder[A,Done]] }
  def result(implicit ev: Builder[A,B] <:< Builder[Done,Done]) = built
}
object Builder {
  def apply() = new Builder[Need, Need]
}

(如果您在REPL中尝试这样做,请确保类和对象生成器定义在同一个块中,即使用:paste。)使用<:<检查类型、泛型类型参数以及case类的copy方法的组合形成了一个非常强大的组合。

工厂方法的主要用途是保持类型的完整性;否则,您不妨使用构造函数。使用Scala强大的类型系统,您不需要帮助来保持类型的完整性,因此您可以在类的同伴对象中使用构造函数或apply方法,并以这种方式创建东西。特别是在伴随对象的情况下,保持接口的一致性并不比保持工厂对象中的接口的一致性困难。因此,工厂对象的大部分动机都没有了。

类似地,抽象工厂方法的许多情况可以通过从适当的特征继承一个伴生对象来替换。

当然,重写的方法和类似的方法在Scala中有自己的位置。然而,Design Patterns web站点上的原型模式所使用的示例在Scala(或Java IMO)中是不可取的。但是,如果您希望一个超类根据它的子类选择操作,而不是让子类自己决定,那么您应该使用match而不是笨重的instanceof测试。

Scala通过object包含了这些内容。他们是单身的--使用和享受!

Scala的trait在这里提供了更多的功能--不是创建实现接口的类,例如,您可以创建一个只实现接口的一部分的trait,剩下的由您定义。例如,java.awt.event.MousEmotionListener要求您填写两个方法:

def mouseDragged(me: java.awt.event.MouseEvent)
def mouseMoved(me: java.awt.event.MouseEvent)

也许你想忽略拖动。然后编写特征:

trait MouseMoveListener extends java.awt.event.MouseMotionListener {
  def mouseDragged(me: java.awt.event.MouseEvent) {}
}
trait MouseMotioner extends java.awt.event.MouseMotionListener {
  def mouseMotion(me: java.awt.event.MouseEvent, drag: Boolean): Unit
  def mouseMoved(me: java.awt.event.MouseEvent) { mouseMotion(me, false) }
  def mouseDragged(me: java.awt.event.MouseEvent) { mouseMotion(me, true) }
}

复合模式特别容易用case类实现,尽管进行更新相当费力。它在Scala和Java中同样有价值。

装修工很笨拙。如果继承不是您想要的,您通常不想在不同的类上使用相同的方法;您真正想要的是同一个类上的不同方法,它执行您想要的操作,而不是默认的操作。“丰富我的图书馆”模式通常是一种更好的替代方法。

Facade在Scala中比在Java中工作得更好,因为您可以使用带有部分实现的特性,因此在组合它们时不必自己完成所有工作。

在那些可以按顺序列出责任方的情况下,可以

xs.find(_.handleMessage(m))

假设每个人都有一个handleMessage方法,如果消息被处理,该方法返回true。如果您想要更改消息,请改用fold。

由于很容易将责任方放入某种缓冲区中,因此Java解决方案中使用的复杂框架在Scala中很少占有一席之地。

public interface ChangeListener extends EventListener {
  void stateChanged(ChangeEvent e)
}
...
void addChangeListener(ChangeListener listener) { ... }
def onChange(f: ChangeEvent => Unit)

Scala在其标准库中内置了iterator。使您自己的类扩展iteratoriterable几乎是微不足道的;后者通常更好,因为它使重用变得微不足道。这绝对是个好主意,但太简单了,我几乎不认为它是一个模式。

这在Scala中工作得很好,但通常对可变数据很有用,如果不小心使用,甚至中介器也会违反竞争条件等。相反,在可能的情况下,尝试将所有相关数据存储在一个不可变的集合、案例类或其他任何内容中,并且在进行需要协调更改的更新时,同时更改所有内容。这不会帮助您与javax.swing接口,但在其他方面可以广泛应用:

case class Entry(s: String, d: Double, notes: Option[String]) {}

def parse(s0: String, old: Entry) = {
  try { old.copy(s = s0, d = s0.toDouble) }
  catch { case e: Exception => old }
}

保存mediator模式,以备需要处理多个不同关系(每个关系有一个mediator),或者有可变数据时使用。

class OneRandom {
  lazy val value = scala.util.Random.nextInt
}
val r = new OneRandom
r.value  // Evaluated here
r.value  // Same value returned again
class Lazily[A](a: => A) {
  lazy val value = a
}
val r = Lazily(scala.util.Random.nextInt)
// not actually called until/unless we ask for r.value

这充其量是一个脆弱的模式。只要有可能,要么保持不可变的状态(参见Mediator),要么使用actor,其中一个actor向所有其他actor发送关于状态变化的消息,但每个actor都可以处理过时的问题。

这在Scala中同样有用,并且当应用于无方法特性时,实际上是创建枚举的最受欢迎的方法:

sealed trait DayOfWeek
final trait Sunday extends DayOfWeek
...
final trait Saturday extends DayOfWeek

(通常情况下,你会希望工作日做一些事情来证明这一数量的样板是正确的)。

def printElapsedTime(t: Long, rounding: Double => Long = math.round) {
  println(rounding(t*0.001))
}
printElapsedTime(1700, math.floor)  // Change strategy

在结构类型和隐式转换之间,Scala比Java的典型访问者模式具有更多的能力。使用原始模式是没有意义的;你只会从正确的方法上分心。许多示例实际上只是希望在被访问的对象上定义一个函数,而Scala可以为您做一些琐碎的工作(即将任意方法转换为函数)。

 类似资料:
  • 问题内容: 我正在学习GoF Java设计模式,我想看看其中的一些实际示例。Java核心库中的这些设计模式有哪些好的示例? 问题答案: 你可以在Wikipedia中找到许多设计模式的概述。它还提到了GoF提到了哪些模式。我将在这里对其进行总结,并尝试分配尽可能多的模式实现,这些模式实现可在Java SE和Java EE API中找到。 创作模式 抽象工厂 (通过返回工厂本身的创建方法可识别,该工厂

  • 问题内容: java web设计模式有哪些? 问题答案: 模型视图控制器模式 你要使用的核心(架构)设计模式是Model-View-Controller模式。该控制器是由一个Servlet其中(在)直接创造来表示/使用特定的模型和视图基于该请求。该模型将由Javabean类表示。在包含动作(行为)的业务模型和包含数据(信息)的数据模型中,这通常可以进一步划分。该视图是由具有对(直接访问JSP文件来

  • 根据我的理解,flyweight设计模式与工厂或单例设计模式没有太大区别。

  • 在网上搜索和阅读了关于设计模式的文章后,我发现了三种类型,即行为型、创造型和结构型设计模式(GOF)。

  • 我是设计模式领域的新手,我正在尝试了解其中的诀窍。我曾多次听到人们使用的“工厂”或“工厂模式”,但当我开始学习设计模式(目前我正在读GoF的书)时,我了解到实际上并不存在“工厂设计模式”这样的东西。GoF这本书描述了两种与工厂相关的模式:“抽象工厂”和“工厂方法”。 所以我的问题是这样的--当人们只说“工厂”(没有添加任何其他东西)时,他们实际上指的是哪种设计模式? 我找到了两个关于这件事的消息来

  • 本文向大家介绍设计模式构建器模式/Java 实现,包括了设计模式构建器模式/Java 实现的使用技巧和注意事项,需要的朋友参考一下 示例 通过Builder模式,您可以以易于阅读的方式创建具有许多可选变量的类的实例。 考虑以下代码: 如果所有参数都是必需的,那么一切都很好。如果有更多的变量和/或其中一些是可选的怎么办?您不想使用必需参数和可选参数的每种可能的组合来创建大量的构造函数,因为它变得难以