值对象valueObject
值对象代表不可变,不变性,一旦构成就再也不改变。值对象是作为DTO的自然实现。
Java代码需要使用final
public class Point { private final int x, y;
public Point(int x, int y) { this.x = x; this.y = y; }
public int getX() { return x; }
public int getY() { return y; }
public boolean equals(Object o) { // ... return x == that.x && y == that.y; }
public int hashCode() { return 31 * x + y; }
public String toString() { return String.format("Point(%d, %d)", x, y); } }
Point point = new Point(1, 2)
|
Scala主要针对可变和不可变提供var和val两个声明:
val point = (1, 2)
或
type Point = (Int, Int) // Tuple2[Int, Int]
val point: Point = (1, 2)
或
case class Point(x: Int, y: Int)
val point = Point(1, 2)
Null Object空对象
空对象代表一个对象什么也不做。
Java代码:
public interface Sound { void play(); }
public class Music implements Sound { public void play() { /* ... */ } }
public class NullSound implements Sound { public void play() {} } public class SoundSource { public static Sound getSound() { return available ? music : new NullSound(); } } SoundSource.getSound().play();
|
使用空对象就不必检查getSound()是否为空,scala代码:
trait Sound { def play() } class Music extends Sound { def play() { /* ... */ } }
object SoundSource { def getSound: Option[Sound] = if (available) Some(music) else None } for (sound <- SoundSource.getSound) { sound.play() }
|
Scala使用Option。它可以用来作为一个可选值的占位符。
Strategy策略模式
Java代码:
public 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);
|
Scala利用其函数语言的魔力简化了这些方法:
type 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)
|
Command命令模式
java代码:
public 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("foo")); invoker.invoke(new PrintCommand("bar"));
|
Scala使用by-name parameter 实现:
object Invoker { private var history: Seq[() => Unit] = Seq.empty
def invoke(command: => Unit) { // by-name parameter command history :+= command _ } }
Invoker.invoke(println("foo")) Invoker.invoke { println("bar 1") println("bar 2") }
|
个人感觉,虽然很简单,大道至简,但是简单得有点像魔术,属于玄了。
Chain of responsibility职责链
Scala代码:
rait EventHandler { def handle(event: Event) }
class DefaultHandler extends EventHandler { def handle(event: Event) { /* ... */ } }
trait KeyboardHandler extends EventHandler { abstract override def handle(event: Event) { if (event.source == "keyboard") /* ... */ else super.handle(event) } }
trait MouseHandler extends EventHandler { abstract override def handle(event: Event) { if (event.source == "mouse") /* ... */ else super.handle(event) } }
new DefaultHandler with KeyboardHandler with MouseHandler
|
使用trait 和with语法替代了Java的"."