Javaで作る自動販売機（ドメイン駆動）

# 経緯
shiracamus様からのアドバイスを元に、DDD（ドメイン駆動）的に書き直しました。
その際、ロジックの見直しも一部行い、よりシンプルになるように致しました。

# 処理フロー
・インスタンス生成
・商品リスト初期化（在庫補充）
・商品一覧表示（陳列商品の表示）
・商品選択（ユーザによる入力）
・入金（ユーザによる入力）
・販売（課金処理）
・おつり（返金処理）

# 動作イメージ
![venderMachine_DDD.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190809/72d04dbd-2453-92b8-8e58-54c70b90304b.gif)

# ソースコード
```Main.java
package vm;

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        // インスタンス生成
        Store venderMachine = new Store();
        @SuppressWarnings("resource")
        Scanner scanner = new Scanner(System.in);

        // 商品リスト初期化
        Product water = new Product("水", 80);
        Product coke = new Product("コーラ", 100);
        Product orangejuice = new Product("オレンジジュース", 120);
        venderMachine.addStock(water);
        venderMachine.addStock(coke);
        venderMachine.addStock(orangejuice);

        // 商品一覧表示
        System.out.println("≪販売中の商品です≫");
        venderMachine.showProductList();

        // 商品選択
        Product purchase = null;
        String purchaseSelectMessage = "購入する商品名を入力してください。";
        int purchaseSelectCount = 0;
        do {
            if(purchaseSelectCount > 0) {
                purchaseSelectMessage = "その商品の取り扱いはございません。販売中の商品からお選び下さい。";
            }

            System.out.println();
            System.out.println(purchaseSelectMessage);
            purchase = venderMachine.inStocker(scanner.next());
            purchaseSelectCount++;
        } while(!venderMachine.isExistsStock(purchase));


        // 入金
        String depositMessage = "入金して下さい。";
        int depositCount = 0;
        do {
            if(depositCount > 0) {
                depositMessage = "入金額が不足しています。不足分を追加してください。";
            }

            System.out.println();
            System.out.println(depositMessage);
            venderMachine.addDeposit(scanner.nextInt());
            depositCount++;
        } while(!venderMachine.isEnoughDeposit(purchase));

        // 販売
        System.out.println();
        venderMachine.sale(purchase);

        // おつり
        System.out.println();
        venderMachine.change();
    }
}
```

```Store.java
package vm;

public class Store {
    private Stocker stocker;
    private Casher casher;

    Store() {
        stocker = new Stocker();
        casher = new Casher();
    }

    void addDeposit(int deposit) {
        casher.addDeposit(deposit);
    }

    void addStock(Product product) {
        stocker.add(product);
    }

    void change() {
        System.out.println("おつりは、" + casher.change() + "円です。");
    }

    void showProductList() {
        stocker.showProductList();
    }

    boolean isExistsStock(Product product) {
        return stocker.isExistsProduct(product);
    }

    boolean isEnoughDeposit(Product purchase) {
        return casher.isEnoughDeposit(purchase);
    }

    Product inStocker(String productName) {
        return stocker.getProduct(productName);
    }

    void sale(Product purchase) {
        casher.charge(purchase);
        System.out.println(purchase.name() + "です！");
        System.out.println("ご購入ありがとうございました。");
    }

}
```

```Casher.java
package vm;

public class Casher {
    private int deposit;
    private int change;

    Casher(){
        deposit = 0;
        change = 0;
    }

    void addDeposit(int deposit) {
        this.deposit += deposit;
    }

    void charge(Product purchase) {
        change = deposit - purchase.price();
    }

    int change() {
        return change;
    }

    public boolean isEnoughDeposit(Product product) {
        if(deposit >= product.price()) {
            return true;
        }
        return false;
    }

}
```

```Stocker.java
package vm;

import java.util.ArrayList;
import java.util.List;

public class Stocker {
    private List<Product> productList;

    Stocker() {
        productList = new ArrayList<>();
    }

    void add(Product product) {
        productList.add(product);
    }

    void showProductList() {
        for(Product product: productList) {
            System.out.println(product.info());
        }
    }

    boolean isExistsProduct(Product product) {
        for(Product stock: productList) {
            if(stock.name().equals(product.name())){
                return true;
            }
        }
        return false;
    }

    Product getProduct(String productName) {
        for(Product stock: productList) {
            if(stock.name().equals(productName)){
                return stock;
            }
        }
        return new Product();
    }

}
```

```Product.java
package vm;

public class Product {
    private String productName;
    private int price;

    Product(String productName, int price) {
        this.productName = productName;
        this.price = price;
    }

    Product() {
        this.productName = "";
        this.price = 0;
    }

    String name() {
        return productName;
    }

    int price() {
        return price;
    }

    String info() {
        String formatStr = "%s : %d円";
        return String.format(formatStr, productName, price);
    }

}
```