visitor pattern scala way using case classes and pattern matching with real world example

I have covered the visitor pattern explanation in the previous article here is the link for the same scala-visitor-pattern

The visitor design pattern could be represented in a way that is less verbose and closer to Scala using the case classes and pattern matching. Instead of having multiple different visit methods in the Visitor trait we will just have one method which takes a communication provider interface and using pattern matching capability of scala we will run the required algorithm.

Lets code the required interfaces first


trait CommunicationProvider {
val pattern = java.util.regex.Pattern.compile("")
def accept(visitor: VisitorScalaWay1)
}


trait VisitorScalaWay1 {
def sendFiles(cp: CommunicationProvider)

}

Lets add the concrete visitor implementation DynamicLineDataVisitor and the SystemDataVisitor


import scala.collection.mutable.ListBuffer

class DynamicLineDataVisitorScalaWay1(var list: ListBuffer[java.io.File]) extends VisitorScalaWay1 {

def sendFiles(cp: CommunicationProvider) =
{
val pattern = cp.pattern

cp match {

case Airtel() =>
{
list.foreach {
file =>
if (pattern.matcher(file.getName()).matches()) {
println("sending file into "+cp.getClass.getName)

}
}
}
case Vadafone() =>
{
list.foreach {
file =>
if (pattern.matcher(file.getName()).matches()) {
println("sending file into "+cp.getClass.getName)

}
}
}
case Idea() =>
{
list.foreach {
file =>
if (pattern.matcher(file.getName()).matches()) {
println("sending file into "+cp.getClass.getName)

}
}
}

}
}

}


import scala.collection.mutable.ListBuffer

class SystemDataVisitorScalaWay1(var list: ListBuffer[java.io.File]) extends VisitorScalaWay1 {

def sendFiles(cp: CommunicationProvider) =
{
val pattern = cp.pattern

cp match {

case Airtel() =>
{
list.foreach {
file =>
if (pattern.matcher(file.getName()).matches()) {
println("sending file into "+cp.getClass.getName)

}
}
}
case Vadafone() =>
{
list.foreach {
file =>
if (pattern.matcher(file.getName()).matches()) {
println("sending file into "+cp.getClass.getName)

}
}
}
case Idea() =>
{
list.foreach {
file =>
if (pattern.matcher(file.getName()).matches()) {
println("sending file into "+cp.getClass.getName)

}
}
}

}
}

}

Lets add the concrete communication provider implementation


case class Airtel() extends CommunicationProvider {

override val pattern:java.util.regex.Pattern = java.util.regex.Pattern.compile("Airtel_(.*).tar.gz");

def accept(visitor: VisitorScalaWay1) = {

visitor.sendFiles(this)

}

}


case class Idea() extends CommunicationProvider {

override val pattern:java.util.regex.Pattern = java.util.regex.Pattern.compile("Idea_(.*).tar.gz");

def accept(visitor: VisitorScalaWay1) = {

visitor.sendFiles(this)

}

}


case class Vadafone() extends CommunicationProvider {

override val pattern: java.util.regex.Pattern = java.util.regex.Pattern.compile("Vadafone_(.*).tar.gz");

def accept(visitor: VisitorScalaWay1) = {

visitor.sendFiles(this)

}

}

Finally lets code the test class


object Test extends App {

import java.io.File
import scala.collection.mutable.ListBuffer

val file1: File = new File("Airtel_(.*).tar.gz")

val file2: File = new File("Vadafone_(.*).tar.gz")

val file3: File = new File("Idea_(.*).tar.gz")

val listOfFiles = ListBuffer[File]();

listOfFiles += file1

listOfFiles += file2

listOfFiles += file3

val dynamicLineDataVisitor = new DynamicLineDataVisitorScalaWay1(listOfFiles);

val systemDataVisitor = new SystemDataVisitorScalaWay1(listOfFiles);

val airtel = new Airtel();

val vadofone = new Vadafone();

val idea = new Idea();

airtel.accept(dynamicLineDataVisitor);

vadofone.accept(systemDataVisitor);

idea.accept(dynamicLineDataVisitor);

}