定义行为设计模式顾名思义,行为设计模式与行为有关。 它们的目的是识别和实现应用程序中对象之间的通用通信模式。 它们以这样的方式定义对象交互:对象之间的通信很容易,并且耦合仍然保持在低水平。
行为设计模式描述了对象和类如何使用消息相互交互。 与创造和结构设计模式相反,行为设计模式描述了流程或过程。 这意味着开发人员应该非常熟悉他们试图实现的实际过程。 与其他所有类型的设计模式一样,存在行为设计模式,以提高生成代码的可测试性,可维护性和灵活性。
1
示例类图使用迭代器设计模式,我们可以创建自己的对象作为集合,我们可以在循环中使用它们。在Java中,有一个名为Iterator的接口,我们可以为此实现。在Scala中,我们可以混合使用Iterator特性并实现其hasNext和next方法。
对于类图和示例,让我们有一个ClassRoom类,它将支持在所有学生中运行的foreach循环。
下图显示了我们的类图:我们已经决定使用ClassRoom类来实现Iterable,它应该返回一个Iterator,然后在调用方法时返回迭代器的新实例。迭代器设计模式由图的右侧表示。图表的其余部分是我们为使我们的类更容易工作所做的事情。
代码示例让我们看一下实现上图的代码。首先,Student类只是一个案例类,如下所示:
import scala.collection.mutable.ListBuffer case class Student(name: String, age: Int) class StudentIterator(students: Array[Student]) extends Iterator[Student] { var currentPos = 0 override def hasNext: Boolean = currentPos < students.size override def next(): Student = { val result = students(currentPos) currentPos = currentPos + 1 result } } class ClassRoom extends Iterable[Student] { val students: ListBuffer[Student] = ListBuffer[Student]() def add(student: Student): Unit = { student +=: students } override def iterator: Iterator[Student] = new StudentIterator(students.toArray) } object ClassRoomExample { def main(args: Array[String]): Unit = { val classRoom = new ClassRoom classRoom.add(Student("Ivan", 26)) classRoom.add(Student("Maria", 26)) classRoom.add(Student("John", 25)) classRoom.foreach(println) } }
关于迭代器的一件事就是它们只能在一个方向上工作而你却无法返回。这就是为什么我们只使用currentPos变量来记住我们在迭代中的距离。我们在这里使用了一个可变变量,它违背了Scala原则;然而,这只是一个例子,并不是太关键。
实际上,您可能会将迭代器设计模式与数据结构结合使用,而不是使用此形式。我们选择迭代器的底层结构为Array的原因是数组的索引访问是不变的,它将提高大型集合的性能并使我们的实现简单。
我们在前面的代码中混合了Iterable trait并实现了它的迭代器方法。我们返回StudentIterator。
我们已经创建了一个自定义迭代器作为示例。但是,实际上,您只需在ClassRoom类中实现Iterable并返回底层集合的迭代器(在本例中为学生)。
我们在Iterable特征中混合的事实允许我们使用foreach,map,flatMap和ClassRoom类型的对象上的许多其他人。
以下屏幕截图显示了我们示例的输出:
正如您在本示例中所看到的,我们的ClassRoom类的用户不知道保存Student对象的基础数据结构。我们可以随时替换它(我们甚至可以从数据库中获取学生的数据),只要我们在class上仍然具有Iterable特性,整个代码就会继续工作。
迭代器设计模式的优点: 迭代器设计模式一直在软件工程中使用。它可能是最常用的设计模式之一,每个人都知道它。它几乎可以用于所有可以想到的集合,它非常简单,并且允许我们隐藏复合对象在内部组织的细节。
迭代器设计模式的缺点,它显示了迭代设计模式的一个可能的问题,是它在并行代码中的使用。如果另一个线程在原始集合中添加或删除对象会发生什么?我们的迭代器不会反映这一点,并且由于缺乏同步而可能导致问题。使迭代器能够处理多线程环境并不是一项简单的任务。