Scala 设计模式:创建型模式

工厂方法

简单的说,工厂方法( factory method)提供了一个接口用来创建对象,并且用一个方法来封装对象实例的创建,可以通过子类来决定创建什么具体的对象。

使用工厂方法可以带来以下好处:

  • 将复杂的对象创建代码简单化为一个方法调用。
  • 可以创建不同类的实例。
  • 缓存对象。
  • 对共享资源提供一致性访问方式。.

我们可以考虑使用静态工厂方法(static factory method),这种方式和经典的模式稍有不同,它避免了子类,但是也没有办法来重载(override)这个方法。

在Java中,我们用 new 来调用类的构造函数来实例化一个类。为了实现这个模式,我们使用普通的方式,也就是使用类中的静态方法。

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");

除了直接调用构造函数,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")

工厂方法定义在一个伴随对象(一个和类型同名的特殊的单例对象)中。下面是这种方式的优劣:

优势:
  • 重用基类的名字。
  • 标准、简洁。
  • 比较象构造函数的调用。
劣势:
  • 使用了静态方法。





延迟初始化

延迟初始化(Lazy initialization)是一种特殊的延迟求值的策略,它是一种在对象被初次访问时才初始化的技术。使用它可以推迟(或避免)一些耗时的计算。

Java中比较典型的实现是使用 null 来表示未初始化的状态,但是,如果 null 是一个有用的状态的化,那么就需要用一个单独的标记来说明初始化的过程是不是已经发生。

在多线程环境中需要使用synchronized 来避免不必要的竞争,甚至可以使用 double-checked locking 来保证更有效的同步,这样也会使代码变得更复杂。

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

scala用一个干净的内建语法来定义懒值(lazy value)

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

print("x = ") 
println(x) 

// x = (computing x) 42


懒值在scala中可以使用 null,对懒值的访问是线程安全(thread-safe)的。下面是这种模式的优劣:

优势:
  • 代码简洁.
  • 懒值可以使用null.
  • 懒值是线程安全的。
劣势:
  • 对初始化过程缺少控制




单例

单例模式限制类只能创建一个对象,并且提供了一个唯一访问点。单例模式也许是Java中最知名的设计模式,下面是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()


Scala通过语言提供了一个简洁直接的实现:

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

Cat.run()


在scala中,object可以从类或者接口中继承方法,object可以直接或者通过接口去访问,object在第一次使用时被初始化。

优势:
  • 含义清晰。
  • 语法简洁。
  • 需要时初始化。
  • 线程安全。
劣势:
  • 不容易通过初始化来控制。





这篇文章主要是翻译Design Patterns in Scala,但有所缩减和改动。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值