Last active
October 15, 2018 09:29
-
-
Save lbialy/912fad3c909374b81ce7 to your computer and use it in GitHub Desktop.
Scala - multiple approaches to Specification Pattern
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Specification { | |
type Spec[-A] = A => Boolean | |
implicit class SpecOps[A](_this: Spec[A]) { | |
def and(that: Spec[A]) = (item: A) => _this(item) && that(item) | |
def or(that: Spec[A]) = (item: A) => _this(item) || that(item) | |
def not = (item: A) => !_this(item) | |
} | |
} | |
import Specification._ | |
case class Person(name: String, surname: String, gender: String) | |
val me = Person("Łukasz", "Biały", "M") | |
val hasMyName = (person: Person) => person.name == "Łukasz" | |
val hasMySurname = (person: Person) => person.surname == "Biały" | |
val isAGirl = (person: Person) => person.gender == "F" | |
val isMe = hasMyName and hasMySurname and isAGirl not | |
isMe(me) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Specification { | |
type Spec[-A] = A => Boolean | |
def and[A](_this: Spec[A], that: Spec[A]) = (item: A) => _this(item) && that(item) | |
def or[A](_this: Spec[A], that: Spec[A]) = (item: A) => _this(item) || that(item) | |
def not[A](_this: Spec[A]) = (item: A) => !_this(item) | |
} | |
import Specification._ | |
case class Person(name: String, surname: String, gender: String) | |
val me = Person("Łukasz", "Biały", "M") | |
val hasMyName = (person: Person) => person.name == "Łukasz" | |
val hasMySurname = (person: Person) => person.surname == "Biały" | |
val isAGirl = (person: Person) => person.gender == "F" | |
val isMe = and(and(hasMyName, hasMySurname), not(isAGirl)) | |
isMe(me) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Specification[A] { | |
def isSatisfiedBy(item: A): Boolean | |
def and(that: Specification[A]) = new And(this, that) | |
def or(that: Specification[A]) = new Or(this, that) | |
def not() = new Not(this) | |
} | |
class And[A](val left: Specification[A], val right: Specification[A]) extends Specification[A] { | |
override def isSatisfiedBy(item: A) = (left isSatisfiedBy item) && (right isSatisfiedBy item) | |
} | |
class Or[A](val left: Specification[A], val right: Specification[A]) extends Specification[A] { | |
override def isSatisfiedBy(item: A) = (left isSatisfiedBy item) || (right isSatisfiedBy item) | |
} | |
class Not[A](val spec: Specification[A]) extends Specification[A] { | |
override def isSatisfiedBy(item: A) = !(spec isSatisfiedBy item) | |
} | |
case class Person(name: String, surname: String, gender: String) | |
class HasMyName extends Specification[Person] { | |
def isSatisfiedBy(person: Person) = person.name == "Łukasz" | |
} | |
class HasMySurname extends Specification[Person] { | |
def isSatisfiedBy(person: Person) = person.surname == "Biały" | |
} | |
class IsAGirl extends Specification[Person] { | |
def isSatisfiedBy(person: Person) = person.gender == "F" | |
} | |
val me = Person("Łukasz", "Biały", "M") | |
val isMe = (new HasMyName) and (new HasMySurname) and ((new IsAGirl) not) | |
isMe.isSatisfiedBy(me) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment