40
Java design patterns in Scala Radim Pavlicek

Java patterns in Scala

Embed Size (px)

Citation preview

Page 1: Java patterns in Scala

Java design patterns in Scala

Radim Pavlicek

Page 2: Java patterns in Scala

About me

● Java/Scala developer● bogey golfer● piano player

Page 3: Java patterns in Scala

Agenda

Page 4: Java patterns in Scala

Part I - OO PatternsFunctional InterfaceCommandBuilderIterator

Template methodStrategyNull Object

Page 5: Java patterns in Scala

Functional Interfaceencapsulate a bit of program logic and treated like any other first-class construct

Page 6: Java patterns in Scala

JavaCollections.sort(people,

new Comparator<Person>() {public int compare(Person p1, Person p2) {

return p1.getFirstName().compareTo(ps.getFirstName())

}})

Page 7: Java patterns in Scala

Javaother use-cases● runnable● callable

Java 8 has solved

Page 8: Java patterns in Scala

Scalapeople.sortWith(

(p1, p2) => p1.firstName < p2.firstName)

Page 9: Java patterns in Scala

CommandTurn a method invocation into an objectand execute it in a central location

Page 10: Java patterns in Scala

Javapublic class PrintCommand implements Runnable { private final String s; PrintCommand(String s) { this.s = s; } public void run() { System.out.println(s); }}

public class Invoker { private final List<Runnable> history = new ArrayList<>(); void invoke(Runnable command) { command.run(); history.add(command); }}Invoker invoker = new Invoker();invoker.invoke(new PrintCommand("Scala"));invoker.invoke(new PrintCommand("Vienna"));

Page 11: Java patterns in Scala

Scalaobject Invoker { private var history: Seq[() => Unit] = Seq.empty

def invoke(command: => Unit) { // by-name parameter command history :+= command _ }}

Invoker.invoke(println( "foo"))

Page 12: Java patterns in Scala

Scala advanceddef makePurchase(register: CaschRegister, amount: Int) =

{

() = {

println("Purchase in amount: " + amount)

register.addCash(amount)

}

}

// how to create purchase functions using closure

Page 13: Java patterns in Scala

Builderto create an immutable object using a friendly syntax

Page 14: Java patterns in Scala

Java Issues● constructor arguments

Person(String n,String n2,String nick● Defaults (telescoping constructor problem)

Person()Person(String name)Person(String name, String name2)...

Page 15: Java patterns in Scala

Java codepublic class ImmutablePerson {

private final String firstName;

public String getFirstName() {

return firstName;}

private ImmetablePerson(Builder builder) {

firstName = builder.firstName;

}

public static Builder newBuilder() {

return new Builder();

}

}

public static class Builder { private String firstName; public Builder withFirstName(String firstName) { this.firstName = firstName; return this; } public ImmutablePerson build () { return new ImmutablePerson(this); } }

Page 16: Java patterns in Scala

Scala - Case Classcase class Person {

firstName: String,

LastName: String,

nick: String = "")

val p = Person(firstName = “Radim”, lastName = “Pavlicek”)

val cloneMe = Person(firstName = “Radim”, lastName = “Pavlicek”)

p.equals(cloneMe) // true

val brother = p.copy(firstName = “Libor”) // Libor Pavlicek

p.toString // Person[firstName=”Radim”, lastName= “Pavlicek”]

Page 17: Java patterns in Scala

Scala - Tuples● for explorative development

def p = (“Radim”, “Pavlicek”)p._1 // Radimp._2 // Pavlicek

Page 18: Java patterns in Scala

Iteratoriterate through the elements of a sequence without having to index into it

Page 19: Java patterns in Scala

Javapublic Set<Char> vowelsCount(String s) {

Set<Char> l = new HashSet<Char>(); for (Char c : s.toLowerCase().toCharArray())

if (isVowel(c))l.add(c)

}

Page 20: Java patterns in Scala

Scala● filter● map● reduce

Page 21: Java patterns in Scala

Scala filterfiltering certain elements from collection

def vowelsNumber(word : String) = word.filter(isVowel).toSet

vowelsNumber(“Radim”) // Set(‘a’, ‘i’)

Page 22: Java patterns in Scala

Scala mapfunction is applied to each element

def prependHello(names : Seq[String]) = names.map((name) => “Hello, “ + name)

Page 23: Java patterns in Scala

Scala reducereduce sequence to a single value

def sum(sq : Seq[Int]) = if (sq.isEmpty) 0 else sq.reduce((acc,curr) => acc + curr)

Page 24: Java patterns in Scala

Scala comprehensions● guard

for (a <- list if isEven(a))● pattern matching

for (Person(name, address) <- people)● still no mutable state

Page 25: Java patterns in Scala

Scala for comprehensionscase class Person(name: String, addr: Address)case class Address(zip: Int)def greetings(people: Seq[Person]) =for (Person(name, address) <-

people if isCloseZip(address.zip) )yield “Hello, %s”.format(name)

Page 26: Java patterns in Scala

Template methoddefines the program skeleton of an algorithm in a method, called template method, which defers some steps to subclasses

Page 27: Java patterns in Scala

Javapublic abstract class Template {

public void doStuff() {beforeStuff(); afterStuff();

}protected abstract void beforeStuff();protected abstract void afterStuff();

}

Page 28: Java patterns in Scala

Scala Function Builderdef doStuff(

beforeStuff: () => Unit,afterStuff: () => Unit) =

() = {beforeSuff()afterStuff()

}

Page 29: Java patterns in Scala

Scala Function Builderdef beforeStuff() = Console.println(“before”)def afterStuff() = Console.println(“after”)val test= doStuff(beforeStuff, afterStuff)

scala> test

Page 30: Java patterns in Scala

Strategydefine an algorithm in abstract terms and make it interchangeable within family

Page 31: Java patterns in Scala

Javapublic interface Strategy { int compute(int a, int b);}

public class Add implements Strategy { public int compute(int a, int b) { return a + b; }}

public class Multiply implements Strategy { public int compute(int a, int b) { return a * b; }}

public class Context { private final Strategy strategy;

public Context(Strategy strategy) { this.strategy = strategy; }

public void use(int a, int b) { strategy.compute(a, b); }}

new Context(new Multiply()).use(2, 3);

Page 32: Java patterns in Scala

Scaladefine type alias and use first-class functionstype Strategy = (Int, Int) => Int

class Context(computer: Strategy) { def use(a: Int, b: Int) { computer(a, b) }}

val add: Strategy = _ + _

val multiply: Strategy = _ * _

new Context(multiply).use( 2, 3)

Page 33: Java patterns in Scala

Null Objectavoid null checks in code andcentralize logic that deals with handling the absence of a value

Page 34: Java patterns in Scala

Javaclass NullPerson extends Person {....}public Person build(String first, String last) {

if (first == null || last == null) return new NullPerson();

return new Person (first, last);}

Page 35: Java patterns in Scala

Scalaval nullPerson = Person() // case classdef build(first: Option[String],

last: Option[String]) = (for (f <- first; l <- last)

yield Person(f, l)).getOrElse(nullPerson)

Page 36: Java patterns in Scala

Decoratoradd behaviour to an existing classaka “there is a bug in the API class”

Page 37: Java patterns in Scala

Javapublic interface OutputStream { void write(byte b); void write(byte[] b);}

public class FileOutputStream implements OutputStream { /* ... */ }

public abstract class OutputStreamDecorator implements OutputStream { protected final OutputStream delegate;

protected OutputStreamDecorator(OutputStream delegate) { this.delegate = delegate; }

public void write(byte b) { delegate.write(b); } public void write(byte[] b) { delegate.write(b); }}

Page 38: Java patterns in Scala

Scaladef add(a: Int, b: Int) = a + bdef decorateLogger(calcF: (Int, Int) => Int) =

(a: Int, b: Int) => {val result = calcF(a, b)println(“Result is: “ + result) // here it comesresult

}

Page 39: Java patterns in Scala

Scalaval loggingAdd = decorateLogger(add) scala> loggingAdd(1,4)Result is 5

Page 40: Java patterns in Scala

Sourceshttp://pavelfatin.com/design-patterns-in-scala