ababup1192
9/5/2017 - 2:06 AM

Car.scala

// Factoryを使わない例

// Carのインスタンスの責務とCar全体の責務が混在している。
// staticと非staticの書き分けが面倒。
class Car {
    private int id;
    private String name;

    // Car自体が車の総台数を所持している?
    private static int numOfCar = 0;

    private Car(int id, String name) {
        this.id = id;
        this.name = name;
    }

    // Car自身が自分を作る?
    public static Car create(String name) {
        return new Car(++numOfCar, name);
    }

    public static int getNumOfCar() {
        return numOfCar;
    }

    public String toString(){
        return "Car(" + id + ", " + name + ")";
    }
}

class NoFactory {
    public static void main(String... args) {
        // エラー
        // new Car(1, "Honda");
        System.out.println(Car.create("Honda"));
        System.out.println(Car.create("Toyota"));
        System.out.println(Car.create("Suzuki"));
        System.out.println(Car.getNumOfCar());
      
      /*
      Car(1, Honda)
      Car(2, Toyota)
      Car(3, Suzuki)
      3
      */
    }
}
// 責務は分けられたが・・・
class Car {
    private int id;
    private String name;

    // Factoryクラスからアクセスするために、publicになってしまった。
    public Car(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public String toString(){
        return "Car(" + id + ", " + name + ")";
    }
}

class CarFactory {
    private static int numOfCar = 0;

    public static Car create(String name) {
        return new Car(++numOfCar, name);
    }

    public static int getNumOfCar() {
        return numOfCar;
    }
}

class Factory {
    public static void main(String... args) {
        // エラー・・・ならない!(危険)
        // new Car(123, "Honda");
        // Factory経由が面倒
        System.out.println(CarFactory.create("Honda"));
        System.out.println(CarFactory.create("Toyota"));
        System.out.println(CarFactory.create("Suzuki"));
        System.out.println(CarFactory.getNumOfCar());
      
      /*
      Car(1, Honda)
      Car(2, Toyota)
      Car(3, Suzuki)
      3
      */
    }
}
// 本体はとてもシンプル, コンストラクタはprivate
case class Car private(id: Int, name: String)

// class Carと同名だが別物(シングルトン)、責務が完全に分けられていて かつ staticキーワードは要らない。
object Car {
  private var _numOfCar = 0

  // 呼び出し時に .apply は省略可
  def apply(name: String) = {
    _numOfCar += 1
    new Car(_numOfCar, name)
  }

  def numOfCar = _numOfCar
}

object Main extends App {
  // エラー
  // new Car(123, "Honda");
  
  // 自然で短い! 単純に Carのインスタンスを作っているだけに見える!
  println(Car("Honda"))
  println(Car("Toyota"))
  println(Car("Suzuki"))
  println(Car.numOfCar)
  /*
    Car(1,Honda)
    Car(2,Toyota)
    Car(3,Suzuki)
    3
  */
}