java:クラスを使って買い物システムを作ってみた

# はじめに
この度はこの記事をご覧いただきありがとうございます。今回はクラスについて学んだことを活かして商品の在庫管理と買い物のシステムを作成いたしました。アドバイス等あればご教授ください！

# システム概要
まず、商品を表す`Product`クラス、商品棚を表す`ProductShelf`、商品を入れるカートを表す`Cart`クラスを定義。その後これらのクラスを使って`App.java`で商品棚に商品を追加、削除し、追加された商品を実際にカートに入れて購入するシステムを作成した。
また、`Product`、`ProductShelf`、`Cart`は`Package`というパッケージ内に入っている。

# クラスの概要
今回使用したクラスのファイルを以下に記述する。
## Product
```java
package Package;
public class Product {
    //商品名
    private String name;
    //商品の値段
    private int price;
    //商品の在庫数
    private int stock;
    //商品の数量
    private int much;

    //コンストラクタ(商品の追加)
    public Product(String name){
        setName(name);
    }
    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public int getPrice() {
        return this.price;
    }

    public void setStock(int stock) {
        this.stock = stock;
    }

    public int getStock() {
        return this.stock;
    }

    public void setMuch(int much) {
        this.much = much;
    }

    public int getMuch() {
        return this.much;
    }

}
```
`Product`は以下のフィールドを持っている。
・商品名を表す`String`型の`name`
・商品の値段を表す`int`型の`price`
・商品の在庫数を表す`int`型の`stock`
・カートに入っている商品の数を表す`int`型の`much`
そして、それぞれのフィールドのSetterとGetterのメソッドを持っている。
また、今回はカプセル化を行うため、フィールドのアクセス修飾子は全て`private`で定義した。

## ProductShelf
```java
package Package;
import java.util.*;

public class ProductShelf {
    private ArrayList<Product> productsShelf = new ArrayList<>();

    public ArrayList<Product> getProductsShelf(){
        return this.productsShelf;
    }
    
    public void printInfo(ProductShelf productsShelf){
        for(int i = 0; i < productsShelf.productsShelf.size(); i++){
            System.out.println("商品名 : " + productsShelf.productsShelf.get(i).getName() + "　価格 : " + productsShelf.productsShelf.get(i).getPrice() + "円  在庫数 : " + productsShelf.productsShelf.get(i).getStock());
        }
    }

    public void add(Product product, int stock){
        this.productsShelf.add(product);
        product.setStock(stock);
        System.out.println(product.getName() + "を" + stock + "個追加しました。");
    }

    public void remove(Product product){
        this.productsShelf.remove(product);
        System.out.println(product.getName() + "を削除しました。");
    }

    public void restock(Product product, int much){
        product.setStock(product.getStock() + much);
        System.out.println(product.getName() + "を" + much + "個追加しました。");
    }

    //名前から商品を探すメソッド
    public boolean searchProduct(String name){
        for(int i = 0; i < this.getProductsShelf().size(); i++){
            if (name.equals(this.getProductsShelf().get(i).getName())) {
                return true;
            }
        }
        return false;
    }

    //名前から商品を探して取り出すメソッド
    public Product searchProduct_return(String name){
        for(int i = 0; i < this.getProductsShelf().size(); i++){
            if (name.equals(this.getProductsShelf().get(i).getName())) {
                return this.getProductsShelf().get(i);
            }
        }
        return null;
    }
}
```

`ProductShelf`は以下のフィールドとメソッドを持っている。
・商品棚そのものを表す`Product`型の可変式リスト`productsShelf`
・`productsShelf`のGetterである`getProductsShelf`メソッド
・商品棚の中身を表示する`printInfo`メソッド
・商品棚に商品を追加する`add`メソッド
・商品棚にある商品を削除する`remove`メソッド
・商品棚にある商品の在庫を追加する`restock`メソッド
・商品棚に指定の商品があるか確かめる`searchProduct`メソッド
・商品棚に指定の商品があるか確かめ、その商品を取り出す`searchProduct_return`メソッド
また、今回はカプセル化を行うため、フィールドのアクセス修飾子は全て`private`で定義した。

## Cart
```java
package Package;
import java.util.*;

//カートの中身を表すクラス
public class Cart {
    //商品のリストを表す配列
    private ArrayList<Product> productsList = new ArrayList<>();
    //カート内の合計金額
    private int sumPrice;

    public void setProdactsList(ArrayList<Product> prodactsList) {
        this.productsList = prodactsList;
    }

    public ArrayList<Product> getProdactsList() {
        return this.productsList;
    }
    //カート内の合計金額を求める関数
    public void setSumPrice(Cart cart) {
        this.sumPrice = 0;
        for(int i = 0; i < cart.productsList.size(); i++){
            this.sumPrice += cart.productsList.get(i).getPrice() * cart.productsList.get(i).getMuch();
        }
    }

    public int getSumPrice() {
        return this.sumPrice;
    }

    //カートの中身を表示するメソッド
    public void printCart(Cart cart){
        for(int i = 0; i < cart.productsList.size(); i++){
            System.out.println("商品名 : " + cart.productsList.get(i).getName() + " 数量 : " + cart.productsList.get(i).getMuch() + "　在庫数 : " + cart.productsList.get(i).getStock());
        }
    }

    //名前から商品を探すメソッド
    public boolean searchProduct(String name){
        for(int i = 0; i < this.getProdactsList().size(); i++){
            if (name.equals(this.getProdactsList().get(i).getName())) {
                return true;
            }
        }
        return false;
    }

    //名前から商品を探して取り出すメソッド
    public Product searchProduct_return(String name){
        for(int i = 0; i < this.getProdactsList().size(); i++){
            if (name.equals(this.getProdactsList().get(i).getName())) {
                return this.getProdactsList().get(i);
            }
        }
        return null;
    }

    //カートに商品を追加するメソッド
    public void addProduct(Product product, int much){
        this.productsList.add(product);
        product.setMuch(much);
        product.setStock(product.getStock() - much);
        System.out.println(product.getName() + "を" + product.getMuch() + "個カートに追加しました。");
        this.setSumPrice(this);
        System.out.println("合計金額 = " + this.getSumPrice());
    }

    //カートから商品を削除するメソッド
    public void removeProduct(Product product){
        product.setStock(product.getStock() + product.getMuch());
        product.setMuch(0);
        this.productsList.remove(product);
        System.out.println(product.getName() + "をカートから削除しました。");
        this.setSumPrice(this);
        System.out.println("合計金額 = " + this.getSumPrice());
    }

    //カート内の商品の数量を変更するメソッド
    public void changeMuch(Product product, int much){
        product.setMuch(much);
        System.out.println("数量を" + product.getMuch() + "に変更しました。");
        this.setSumPrice(this);
        System.out.println("合計金額 = " + this.getSumPrice());
    }

    //購入するメソッド
    public void buy(){
        System.out.println("--------------注文内容---------------");
        for(int i = 0; i < this.productsList.size(); i++){
            System.out.println(this.productsList.get(i).getName() + "・・・・" + this.productsList.get(i).getMuch() + "個");
        }
        System.out.println("合計金額 = " + this.getSumPrice());
        this.productsList = null;
        this.sumPrice = 0;
        
    }
}

```

`Cart`は以下のフィールドとメソッドを持っている。
・カートそのものを表す`Product`型の可変式リスト`productsList`
・カート内の合計金額を表す`int`型の`sumPrice`
・`productsList`のSetterである`setProductsList`メソッド
・`productsList`のGetterである`getProductsList`メソッド
・カートの合計金額を求める`setSumPrice`メソッド
・カートの合計金額の値を返す`getSumPrice`メソッド
・カートの中身を表示する`printCart`メソッド
・名前からカート中の商品があるか確かめる`searchProduct`メソッド
・名前からカートの中の商品を探して取り出す`searchProduct_return`メソッド
・カートに商品を追加する`addProduct`メソッド
・カートから商品を削除する`removeProduct`メソッド
・カート内の商品の数量を変更する`changeMuch`メソッド
・カート内の全商品を購入する`buy`メソッド
また、今回はカプセル化を行うため、フィールドのアクセス修飾子は全て`private`で定義した。

## App.java
```java
import Package.*;
import java.util.*;

public class App {
    public static void main(String[] args) throws Exception {
        boolean flag = true;
        ProductShelf productShelf = new ProductShelf();
        Cart cart = new Cart();

        Scanner scanner = new Scanner(System.in);
        
        while(flag){
            System.out.println("操作コマンドを入力してください。");
            String command = scanner.nextLine();
            
            switch (command) {
                
                //商品棚の状態を表示する
                case "PRINT_INFO":
                    productShelf.printInfo(productShelf);
                    break;
                
                //商品を追加する
                case "ADD":
                    System.out.print("商品名を入力してください。 : ");
                    String name = scanner.nextLine();
                    Product product = new Product(name);
                    //商品棚に指定した名前の商品がない場合
                    if (!productShelf.searchProduct(name)) {
                        System.out.print("商品の価格を入力してください。 : ");
                        int price = Integer.parseInt(scanner.nextLine());
                        product.setPrice(price);
                        System.out.print("在庫数を入力してください。 : ");
                        int stock = Integer.parseInt(scanner.nextLine());
                        product.setStock(stock);
                        productShelf.add(product, stock);
                    }else{
                        System.out.print("追加する在庫数を入力してください。： ");
                        int add_stock = Integer.parseInt(scanner.nextLine());
                        product = productShelf.searchProduct_return(name);
                        productShelf.restock(product, add_stock);
                    }
                    
                    break;
                //商品を削除する
                case "REMOVE":
                    System.out.print("削除したい商品名を入力してください。 : ");
                    name = scanner.nextLine();

                    for(int i = 0; i < productShelf.getProductsShelf().size(); i++){

                        if (name.equals(productShelf.getProductsShelf().get(i).getName())) {
                            productShelf.remove(productShelf.getProductsShelf().get(i));
                        }
                        else{
                            System.out.println("該当する商品はありません。");
                        }
                    }
                    break;
                
                //商品の在庫を増やす
                case "RESTOCK":
                    System.out.print("在庫を増やす商品名を入力してください。 : ");
                    name = scanner.nextLine();
                    System.out.print("増やす数を入力してください。 : ");
                    int stock = Integer.parseInt(scanner.nextLine());

                    for(int i = 0; i < productShelf.getProductsShelf().size(); i++){
                        if (productShelf.searchProduct(name)) {
                            productShelf.restock(productShelf.getProductsShelf().get(i), stock);
                        }
                        else{
                            System.out.println("該当する商品はありません。");
                        }
                    }
                    break;

                case "ESCAPE":
                    flag = false;
                    break;

                default:
                    System.out.println("入力されたコマンドは定義されていません。");
                    break;
            }
        }

        flag = true;
        System.out.println("買い物モードに移行します。");
        System.out.println();
        while (flag) {
            System.out.println("操作コマンドを入力してください。");
            String command = scanner.nextLine();

            switch (command) {
                case "PRINT_INFO":
                    cart.printCart(cart);    
                    break;

                //カートに商品を追加する
                case "ADD":
                    System.out.print("商品名を入力してください。 : ");
                    String name = scanner.nextLine();
                    
                if (productShelf.searchProduct(name) && !cart.searchProduct(name)) {
                        System.out.print("数量を入力してください。 : ");
                        int much = Integer.parseInt(scanner.nextLine());
                        Product product = productShelf.searchProduct_return(name);
                        //在庫が購入数より多い場合
                        if (product.getStock() >= much) {
                            cart.addProduct(product, much);
                        }
                        //在庫が購入数より少ない場合
                        else{
                            System.out.println("在庫がありません。");
                        }
                    }else if (productShelf.searchProduct(name) && cart.searchProduct(name)) {
                        System.out.print("数量を入力してください。 : ");
                        int much = Integer.parseInt(scanner.nextLine());
                        Product product = productShelf.searchProduct_return(name);
                        //在庫が購入数より多い場合
                        if (product.getStock() >= product.getMuch() + much) {
                            cart.changeMuch(product, much + product.getMuch());
                        }
                        //在庫が購入数より少ない場合
                        else{
                            System.out.println("在庫がありません。");
                        }
                }
                else{
                    System.out.println("該当する商品はありません。");
                }
                break;
                    
                //カートから商品を削除する
                case "REMOVE":
                    System.out.print("削除する商品名を入力してください。 : ");
                    name = scanner.nextLine();

                    //該当する商品が見つかった場合
                    if (cart.searchProduct(name)) {
                        Product product = cart.searchProduct_return(name);
                        cart.removeProduct(product);
                    }
                    else{
                        System.out.println("該当する商品はありません。");
                    }
                    break;
                
                //カートの商品の数量を変更する
                case "CHANGE_MUCH":
                    System.out.print("数量を変更する商品を入力してください。 : ");
                    name = scanner.nextLine();
                    if (cart.searchProduct(name)) {
                        System.out.print("数量を入力してください。 : ");
                        int much = Integer.parseInt(scanner.nextLine());
                        Product product = cart.searchProduct_return(name);
                        if ((product.getStock() + product.getMuch()) >= much) {
                            cart.changeMuch(product, much);
                        }
                        else{
                            System.out.println("在庫がありません。");
                        }
                    }
                    else{
                        System.out.println("該当する商品はありません。");
                    }
                    break;

                case "BUY":
                    cart.buy();
                    break;

                case "ESCAPE":
                    flag = false;
                    System.out.println("ご利用ありがとうございます。");
                    break;
                    
                default:
                    System.out.println("そのコマンドは存在しません。");
                    break;
            }
        }

        scanner.close();
    }
}
```

今回は上記のプログラムを作成した。以下、動作を実行順序通りに記述する。
品棚やカートに対する操作を続けるというフラグである`boolean`型の変数`flag`を宣言し、`true`を代入。
`ProductShelf`と`Cart`クラスのインスタンス、`productShelf`、`cart`を宣言。
キーボードからの入力を受け付けるため、`scanner`を宣言。

-----------------------------以下繰り返し処理--------------------------------
操作コマンドを入力するように表示し、キーボードからの入力を受け付ける。
switch文を用いて、入力されたコマンドに対して操作を変える。

・"PRINT_INFO"の場合
商品棚の中身を表示する。

・"ADD"の場合
商品棚に追加する商品名を入力するように表示しキーボードからの入力を受け付ける。
指定した名前の商品が商品棚にない場合は商品の価格と商品の在庫数を入力させ、商品棚に商品を追加する。
指定した名前の商品が既に商品棚にある場合は追加する在庫数を入力させ、商品棚に在庫を追加する。

・"REMOVE"の場合
商品棚から削除したい商品名を入力するように表示し、キーボードからの入力を受け付ける。
指定した名前の商品が商品棚にある場合、その商品を商品棚から削除する。
指定した名前の商品が商品棚にない場合、その商品が商品棚に存在しないことを表示する。

・"RESTOCK"の場合
在庫数を増やしたい商品の名前を入力するように表示し、キーボードからの入力を受け付ける。その後、どれくらい増やしたいかを入力させる。
該当する商品が商品棚にある場合、その商品の在庫を増やす。
該当する商品が商品棚にない場合、該当する商品がないことを表示する。

・"ESCAPE"の場合
`flag`に`false`を代入し、繰り返し処理を終了する。

・意図しないコマンドが入力された場合
そのコマンドが存在しないことを表示する。
-----------------------------繰り返し処理終了--------------------------------

もう一度`flag`に`true`を代入し、フラグを立ち上げる。
買い物操作に入ることを表示する。

-----------------------------以下繰り返し処理--------------------------------
操作コマンドを入力するように表示し、キーボードからの入力を受け付ける。
switch文を用いて、入力されたコマンドに対して操作を変える。

・"PRINT_INFO"の場合→カートの中身の表示
    `printCart`を用いて`cart.productsList`の中身を表示する。

・"ADD"の場合
カートに追加する商品名を入力するように表示しキーボードからの入力を受け付ける。
商品棚に対象の商品があり、カートの中に対象の商品がない場合は追加したい商品の数量を入力させる。その後、指定した数量が在庫以下の場合、カートに商品を追加する。指定した数量が在庫より多い場合は在庫がないと表示する。その際、商品棚に対象の商品があり、カートの中に対象の商品がある場合はその商品の追加したい数量を入力させる。その後、数量を変更する。商品棚に対象の商品がない場合は該当する商品がないことを表示する。

・"REMOVE"の場合
カートから削除したい商品名を入力するように表示し、キーボードからの入力を受け付ける。
カート内に該当する商品が見つかった場合はその商品をカートから削除する。カート内に該当する商品がなかった場合は商品がなかったことを表示する。

・"CHANGE_MUCH"の場合
数量を変更したい商品名を入力するように表示し、キーボードからの入力を受け付ける。
カート内に該当する商品があった場合は、変更後の数量を入力させ、カート内の商品の数量を変更する。また、その際、変更後の数量が在庫の数を超えていた場合は在庫がないことを表示する。
カート内に該当する商品がなかった場合は該当する商品がないことを表示する。

・"BUY"の場合
`cart`の`buy`メソッドを呼び出し、商品を購入したことを表示する。

・"ESCAPE"の場合
`flag`に`false`を代入し、繰り返し処理を終了する。

・意図しないコマンドが入力された場合
そのコマンドが存在しないことを表示する。

-----------------------------繰り返し処理終了--------------------------------

`scanner`を閉じる。

# 終わりに
最後までご覧いただきありがとうございました。まだ、エンジニアになったばかりで学ぶことがたくさんあるので、これからも能動的に学んでいきたいと思っております。アドバイス等あれば気軽に言って頂けるとありがたいです。