值对象设计模式
值对象设计模式
在编程中,有不同的比较数据的方法。我们可以比较对象标识或它们的值。这些在不同的场景中很有用,在这里,我们将看到对象是什么以及何时可以使用它们。
值对象是小而简单的不可变对象。他们的平等不是基于身份,而是基于价值平等。
值对象用于表示数字,金钱,日期等。它们应该是小而不可变的;否则,更改值可能会导致错误和意外行为。由于它们的不变性,它们在多线程应用程序中非常有用。
它们通常也用作企业应用程序中的数据传输对象。
示例类图在Java等语言中,没有对值对象的直接支持。开发人员最终做的是将字段声明为final并实现hashCode和equals方法。
然而,不变性是一个在Scala中强制实施的概念。我们之前已经看到了代数数据类型(ADT) - 它们也属于价值对象类别。案例类和元组也是不可变的,它们用于实现价值对象设计模式。下面的类图显示了Scala中值对象设计模式的示例:此图实际上没有做任何特殊操作。它是一个名为Date的案例类的表示。这是我们需要做的一切,以实现不变性并能够实现价值对象设计模式。
代码示例在我们的代码示例中,我们将使用Date类。日期在软件产品中非常常用。当然,有些库提供了围绕日期操作的完整功能,但这对于一个例子应该足够好了。首先,这里是Date类表示:case类Date(day:Int,month:String,year:Int)这是获取值对象所需的一切。 Scala通过为hashCode,equals和toString方法创建默认实现,在后台为我们完成所有工作。案例类为我们提供了额外的权力,但这超出了本节的范围。
现在,让我们使用我们的Date类:正如您所看到的,我们将对象用作值。我们应该注意到,在这里,我们绝对没有验证参数;但是,它很容易添加,但与当前示例无关。如果我们现在运行我们的代码,我们将看到以下输出:从前面的输出中可以看出,普通类与case类的工作方式不同,需要执行一些额外的工作才能实现value对象与他们的设计模式。前面结果的原因是默认情况下,类通过引用标识相互比较,而不是通过它们携带的值进行比较。为了改变这一点,应该实现hashCode和equals。 Scala还允许我们覆盖类的==运算符。
替代实现也可以使用Scala中的预定义元组类来实现值对象设计模式。在这种情况下,我们甚至不需要创建我们的类,我们可以编写类似于(3,“March”,2016)的内容。
这将自动具有与值对象相同的特征。有多达22个元素的元组实现,但不建议在实际应用中使用它们,因为可读性和质量会显着降低。此外,两个n元素元组可以被认为是相等的,即使在语义上它们是我们应用中的不同类型的对象。最后但并非最不重要的是,使用case类访问元素比编写tuple._3之类的内容更容易,更易于阅读。
case class Date(
day: Int,
month: String,
year: Int
)
object DateExample {
def main(args: Array[String]): Unit = {
val thirdOfMarch = Date(3, “MARCH”, 2016)
val fourthOfJuly = Date(4, “JULY”, 2016)
val newYear1 = Date(31, “DECEMBER”, 2015)
val newYear2 = Date(31, “DECEMBER”, 2015)
System.out.println(s"The 3rd of March 2016 is the same as the 4th of July 2016: ${thirdOfMarch == fourthOfJuly}")
System.out.println(s"The new year of 2015 is here twice: ${newYear1 == newYear2}")
}
}
class BadDate(
day: Int,
month: String,
year: Int
)
object BadDateExample {
def main(args: Array[String]): Unit = {
val thirdOfMarch = new BadDate(3, “MARCH”, 2016)
val fourthOfJuly = new BadDate(4, “JULY”, 2016)
val newYear1 = new BadDate(31, “DECEMBER”, 2015)
val newYear2 = new BadDate(31, “DECEMBER”, 2015)
System.out.println(s"The 3rd of March 2016 is the same as the 4th of July 2016: ${thirdOfMarch == fourthOfJuly}")
System.out.println(s"The new year of 2015 is here twice: ${newYear1 == newYear2}")
}
}
值对象设计模式的优点: 适用于多线程和创建数据传输对象(DTO)。这在Scala中非常容易实现,许多人每天都在使用它,甚至没有意识到它实际上是一种设计模式。值对象是Scala是一种非常强大的语言这一事实的另一个例子。
除了使用元组在Scala中表示值对象之外,使用此模式没有其他主要缺点。