Top Banner
Java design patterns in Scala Radim Pavlicek
40

Java patterns in Scala

Jul 14, 2015

Download

Software

Radim Pavlicek
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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