Scala設計模式

banq發表於2013-10-14
Design Patterns in Scala一文列舉了Java和Scala實現經典GoF設計模式的不同程式碼,有助於對比兩種語言。

工廠模式:
Java程式碼:

public interface Animal {}

private class Dog implements Animal {}

private class Cat implements Animal {}

public class AnimalFactory {
    public static Animal createAnimal(String kind) {
        if ("cat".equals(kind)) return new Cat();
        if ("dog".equals(kind)) return new Dog();
        throw new IllegalArgumentException();
    }
}

AnimalFactory.createAnimal("dog");
<p class="indent">


Scala的程式碼:

trait Animal
private class Dog extends Animal
private class Cat extends Animal

object Animal {
  def apply(kind: String) = kind match {
    case "dog" => new Dog()
    case "cat" => new Cat()
  }
}

Animal("dog")
<p class="indent">


注意Scala使用了trait替代Java介面,使用Object替代Java的Class。

Lazy initialization懶初始化
懶初始化是懶賦值lazy evaluation的一種特殊實現。

Java程式碼:

private volatile Component component;

public Component getComponent() {
    Component result = component;
    if (result == null) {
        synchronized(this) {
            result = component;
            if (result == null) {
                component = result = new Component();
            }
        }
    }
    return result;
}
<p class="indent">


Scala程式碼:

lazy val x = {
  print("(computing x) ")
  42
}

print("x = ") 
println(x) 
<p class="indent">


Scala引入了lazy語法。

單態Singleton

Java程式碼:

public class Cat implements Runnable {
    private static final Cat instance = new Cat();
 
    private Cat() {}
 
    public void run() {
        // do nothing
    }

    public static Cat getInstance() {
        return instance;
    }
}

Cat.getInstance().run()
<p class="indent">


Scala程式碼:

object Cat extends Runnable {
  def run() {
    // do nothing
  }
}

Cat.run()
<p class="indent">


object語法其實是一個單例物件。

Adapter介面卡

Java程式碼:

public interface Log {
    void warning(String message);
    void error(String message);
}

public final class Logger {
    void log(Level level, String message) { /* ... */ }
}

public class LoggerToLogAdapter implements Log {
    private final Logger logger;

    public LoggerToLogAdapter(Logger logger) { this.logger = logger; }

    public void warning(String message) {
        logger.log(WARNING, message);
    }
    
    public void error(String message) {
        logger.log(ERROR, message);
    }
}

Log log = new LoggerToLogAdapter(new Logger());
<p class="indent">


Scala程式碼:

trait Log {
  def warning(message: String)
  def error(message: String)
}

final class Logger {
  def log(level: Level, message: String) { /* ... */ }
}

implicit class LoggerToLogAdapter(logger: Logger) extends Log {
  def warning(message: String) { logger.log(WARNING, message) }
  def error(message: String) { logger.log(ERROR, message) }
}

val log: Log = new Logger() 
<p class="indent">


Scala使用了語法implicit,隱式語法,它不是全域性變數,也不是trait那樣動態注入,隱藏魔法吧,在因果論中因有兩種形式,顯式因和隱式因,隱式因是無法顯式看到的,所以new Logger還是之前原始類名,但是其實已經被調包。

Decorator介面卡

public 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); }
}

public class BufferedOutputStream extends OutputStreamDecorator {
    public BufferedOutputStream(OutputStream delegate) {
        super(delegate);
    }

    public void write(byte b) {
        // ...
        delegate.write(buffer)
    }
}

new BufferedOutputStream(new FileOutputStream("foo.txt"))
<p class="indent">


Scala程式碼:

trait OutputStream {
  def write(b: Byte)
  def write(b: Array[Byte])
}

class FileOutputStream(path: String) extends OutputStream { /* ... */ }

trait Buffering extends OutputStream {
  abstract override def write(b: Byte) {
    // ...
    super.write(buffer)
  }
}

new FileOutputStream("foo.txt") with Buffering 
<p class="indent">

trait語法很適合進行方法攔截或新增。

相關文章