-
Notifications
You must be signed in to change notification settings - Fork 361
[자판기] 장혁수 미션 제출합니다. #175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
zangsu
wants to merge
4
commits into
woowacourse:main
Choose a base branch
from
zangsu:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
[자판기] 장혁수 미션 제출합니다. #175
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,16 @@ | ||
| package vendingmachine; | ||
|
|
||
| import vendingmachine.coin.generator.RandomCoinGenerator; | ||
| import vendingmachine.controller.InitialController; | ||
| import vendingmachine.controller.PurchaseController; | ||
|
|
||
| public class Application { | ||
| private static final InitialController initialController = new InitialController(); | ||
| private static final PurchaseController purchaseController = new PurchaseController(); | ||
|
|
||
| public static void main(String[] args) { | ||
| // TODO: 프로그램 구현 | ||
| VendingMachine vendingMachine = initialController.create(new RandomCoinGenerator()); | ||
| purchaseController.purchase(vendingMachine); | ||
|
|
||
| } | ||
| } |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package vendingmachine; | ||
|
|
||
| import vendingmachine.exception.VendingMachineException; | ||
| import vendingmachine.menu.Menu; | ||
|
|
||
| public class Credit { | ||
| private int money; | ||
|
|
||
| public Credit(int money){ | ||
| validateMoney(money); | ||
| this.money = money; | ||
| } | ||
|
|
||
| private void validateMoney(int money) { | ||
| if(money < 100 || money % 10 != 0){ | ||
| throw VendingMachineException.INVALID_MONEY_VALUE.makeException(); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| public boolean canPurchase(int price){ | ||
| return money >= price; | ||
| } | ||
|
|
||
| public void purchase(Menu menu){ | ||
| if(menu.getPrice() > money){ | ||
| throw VendingMachineException.CANT_PURCHASE.makeException(); | ||
| } | ||
| money -= menu.getPrice(); | ||
| } | ||
|
|
||
| public int getMoney() { | ||
| return money; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| package vendingmachine; | ||
|
|
||
| import java.util.Map; | ||
| import vendingmachine.coin.Coin; | ||
| import vendingmachine.coin.Coins; | ||
| import vendingmachine.menu.Menu; | ||
| import vendingmachine.menu.Menus; | ||
|
|
||
| public class VendingMachine { | ||
| private final Menus menus; | ||
| private final Credit credit; | ||
| private final Coins coins; | ||
|
|
||
| public VendingMachine(Menus menus, Credit credit, Coins coins) { | ||
| this.menus = menus; | ||
| this.credit = credit; | ||
| this.coins = coins; | ||
| } | ||
|
|
||
| public boolean isSellable(){ | ||
| if(menus.isSoldOut()){ | ||
| return false; | ||
| } | ||
| int minPrice = menus.getMinPrice(); | ||
| return credit.canPurchase(minPrice); | ||
| } | ||
|
|
||
| public int getRemainMoney(){ | ||
| return credit.getMoney(); | ||
| } | ||
|
|
||
| public void purchase(String menuName){ | ||
| Menu menu = menus.getMenu(menuName); | ||
| credit.purchase(menu); | ||
| menus.purchase(menu); | ||
| } | ||
|
|
||
| public Map<Coin, Integer> giveChange(){ | ||
| return coins.giveChange(credit.getMoney()); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package vendingmachine.coin; | ||
|
|
||
| import java.util.Arrays; | ||
| import vendingmachine.exception.VendingMachineException; | ||
|
|
||
| public enum Coin { | ||
| COIN_500(500), | ||
| COIN_100(100), | ||
| COIN_50(50), | ||
| COIN_10(10); | ||
|
|
||
| private final int amount; | ||
|
|
||
| Coin(final int amount) { | ||
| this.amount = amount; | ||
| } | ||
|
|
||
| // 추가 기능 구현 | ||
| public static Coin getCoins(int amount){ | ||
| return Arrays.stream(values()) | ||
| .filter(coin -> coin.amount == amount) | ||
| .findFirst() | ||
| .orElseThrow(VendingMachineException.INVALID_COIN_AMOUNT::makeException); | ||
| } | ||
|
|
||
|
|
||
| public int getAmount() { | ||
| return amount; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| package vendingmachine.coin; | ||
|
|
||
| import java.util.EnumMap; | ||
| import java.util.Map; | ||
|
|
||
| public class Coins { | ||
| private final Map<Coin, Integer> coins; | ||
|
|
||
| public Coins(Map<Coin, Integer> coins){ | ||
| this.coins = coins; | ||
| } | ||
|
|
||
| public int getCounts(Coin coin){ | ||
| return coins.get(coin); | ||
| } | ||
|
|
||
| public Map<Coin, Integer> giveChange(int changeMoney){ | ||
| Map<Coin, Integer> changes = new EnumMap<>(Coin.class); | ||
| for(Coin coin: Coin.values()){ | ||
| if(coin.getAmount() > changeMoney){ | ||
| changes.remove(coin); | ||
| continue; | ||
| } | ||
| int count = getCount(changeMoney, coin); | ||
| changes.put(coin, count); | ||
| changeMoney -= coin.getAmount() * count; | ||
| } | ||
|
|
||
| return changes; | ||
| } | ||
|
|
||
| private int getCount(int changeMoney, Coin coin) { | ||
| int count = coins.get(coin); | ||
| while(count * coin.getAmount() > changeMoney){ | ||
| count--; | ||
| } | ||
| return count; | ||
| } | ||
|
|
||
| } |
8 changes: 8 additions & 0 deletions
8
src/main/java/vendingmachine/coin/generator/CoinGenerator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package vendingmachine.coin.generator; | ||
|
|
||
| import java.util.Map; | ||
| import vendingmachine.coin.Coin; | ||
|
|
||
| public interface CoinGenerator { | ||
| Map<Coin, Integer> getCoins(int totalMoney); | ||
| } |
44 changes: 44 additions & 0 deletions
44
src/main/java/vendingmachine/coin/generator/RandomCoinGenerator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| package vendingmachine.coin.generator; | ||
|
|
||
| import camp.nextstep.edu.missionutils.Randoms; | ||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.EnumMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import vendingmachine.coin.Coin; | ||
|
|
||
| public class RandomCoinGenerator implements CoinGenerator{ | ||
|
|
||
| @Override | ||
| public Map<Coin, Integer> getCoins(int totalMoney) { | ||
| EnumMap<Coin, Integer> coins = initCoins(); | ||
| List<Integer> integers = initIntegers(); | ||
| while(totalMoney > 0){ | ||
| int amount = Randoms.pickNumberInList(integers); | ||
| if(amount > totalMoney){ | ||
| continue; | ||
| } | ||
| Coin coin = Coin.getCoins(amount); | ||
| coins.put(coin, coins.get(coin) + 1); | ||
| totalMoney -= amount; | ||
| } | ||
| return coins; | ||
| } | ||
|
|
||
| private static EnumMap<Coin, Integer> initCoins() { | ||
| EnumMap<Coin, Integer> coins = new EnumMap<>(Coin.class); | ||
| Arrays.stream(Coin.values()) | ||
| .forEach(coin -> coins.put(coin, 0)); | ||
| return coins; | ||
| } | ||
|
|
||
| private static List<Integer> initIntegers() { | ||
| List<Integer> integers = new ArrayList<>(); | ||
| integers.add(500); | ||
| integers.add(100); | ||
| integers.add(50); | ||
| integers.add(10); | ||
| return integers; | ||
| } | ||
| } |
56 changes: 56 additions & 0 deletions
56
src/main/java/vendingmachine/controller/InitialController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| package vendingmachine.controller; | ||
|
|
||
| import java.util.List; | ||
| import java.util.function.Supplier; | ||
| import vendingmachine.Credit; | ||
| import vendingmachine.VendingMachine; | ||
| import vendingmachine.coin.Coins; | ||
| import vendingmachine.coin.generator.CoinGenerator; | ||
| import vendingmachine.exception.RetryExceptionHandler; | ||
| import vendingmachine.exception.VendingMachineException; | ||
| import vendingmachine.menu.Menus; | ||
| import vendingmachine.view.InputView; | ||
| import vendingmachine.view.OutputView; | ||
|
|
||
| public class InitialController { | ||
| public VendingMachine create(CoinGenerator generator){ | ||
| Coins coins = get(() -> makeCoins(generator)); | ||
| Menus menus = get(this::makeMenus); | ||
| Credit credit = get(this::getCredit); | ||
| return new VendingMachine(menus, credit, coins); | ||
| } | ||
|
|
||
| private Coins makeCoins(CoinGenerator generator) { | ||
| int coinMoney = getCoinMoney(); | ||
| Coins coins = new Coins(generator.getCoins(coinMoney)); | ||
| OutputView.printCoins(coins); | ||
| return coins; | ||
| } | ||
|
|
||
| private int getCoinMoney() { | ||
| int coinMoney = InputView.getCoinMoney(); | ||
| validateMoney(coinMoney); | ||
| return coinMoney; | ||
| } | ||
|
|
||
| private void validateMoney(int coinMoney) { | ||
| if(coinMoney < 0 || coinMoney % 10 != 0){ | ||
| throw VendingMachineException.INVALID_MONEY_VALUE.makeException(); | ||
| } | ||
| } | ||
|
|
||
| private Menus makeMenus() { | ||
| List<String> menus = InputView.getMenus(); | ||
|
|
||
| return new Menus(menus); | ||
| } | ||
|
|
||
| private Credit getCredit(){ | ||
| int initMoney = InputView.getInitMoney(); | ||
| return new Credit(initMoney); | ||
| } | ||
|
|
||
| private <T> T get(Supplier<T> supplier){ | ||
| return RetryExceptionHandler.get(supplier); | ||
| } | ||
| } | ||
36 changes: 36 additions & 0 deletions
36
src/main/java/vendingmachine/controller/PurchaseController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| package vendingmachine.controller; | ||
|
|
||
| import java.util.Map; | ||
| import vendingmachine.VendingMachine; | ||
| import vendingmachine.coin.Coin; | ||
| import vendingmachine.exception.RetryExceptionHandler; | ||
| import vendingmachine.view.InputView; | ||
| import vendingmachine.view.OutputView; | ||
|
|
||
| public class PurchaseController { | ||
| public void purchase(VendingMachine machine) { | ||
| while (machine.isSellable()) { | ||
| RetryExceptionHandler.run(() ->purchaseMenu(machine)); | ||
| } | ||
| printResult(machine); | ||
| } | ||
|
|
||
| private void printResult(VendingMachine machine) { | ||
| printRemainMoney(machine); | ||
| Map<Coin, Integer> coinIntegerMap = machine.giveChange(); | ||
| OutputView.printChange(coinIntegerMap); | ||
| } | ||
|
|
||
| private static void purchaseMenu(VendingMachine machine) { | ||
| printRemainMoney(machine); | ||
| String menuName = InputView.getMenuName(); | ||
| machine.purchase(menuName); | ||
| } | ||
|
|
||
| private static void printRemainMoney(VendingMachine machine) { | ||
| int remainMoney = machine.getRemainMoney(); | ||
| OutputView.printRemainMoney(remainMoney); | ||
| } | ||
|
|
||
|
|
||
| } |
33 changes: 33 additions & 0 deletions
33
src/main/java/vendingmachine/exception/RetryExceptionHandler.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package vendingmachine.exception; | ||
|
|
||
| import java.util.function.Supplier; | ||
| import vendingmachine.view.io.Printer; | ||
|
|
||
| public class RetryExceptionHandler { | ||
| private RetryExceptionHandler(){} | ||
|
|
||
| public static <T> T get(Supplier<T> supplier){ | ||
| while(true) { | ||
| try{ | ||
| return supplier.get(); | ||
| } catch (IllegalArgumentException e){ | ||
| Printer.printMessage(e.getMessage()); | ||
| } finally { | ||
| Printer.printMessage(""); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public static void run(Runnable runnable){ | ||
| while(true) { | ||
| try{ | ||
| runnable.run(); | ||
| return; | ||
| } catch (IllegalArgumentException e){ | ||
| Printer.printMessage(e.getMessage()); | ||
| } finally { | ||
| Printer.printMessage(""); | ||
| } | ||
| } | ||
| } | ||
| } |
32 changes: 32 additions & 0 deletions
32
src/main/java/vendingmachine/exception/VendingMachineException.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| package vendingmachine.exception; | ||
|
|
||
| public enum VendingMachineException { | ||
| INVALID_NUMBER_FORMAT("숫자를 입력해 주세요"), | ||
| INVALID_MONEY_VALUE("입력 가격이 잘못되었습니다."), | ||
| INVALID_STRING_FORMAT("입력 형식이 잘못되었습니다."), | ||
| END_WITH_DELIMITER("입력의 마지막이 구분자로 끝났습니다."), | ||
|
|
||
| INVALID_COIN_AMOUNT("해당 금액의 동전을 찾을 수 없습니다."), | ||
| EMPTY_MENU_LIST("메뉴가 입력되지 않았습니다."), | ||
| NO_MENU_FOUNDED("해당 메뉴를 찾을 수 없습니다."), | ||
|
|
||
| CANT_PURCHASE("구매할 수 없는 상품입니다."), | ||
| MENU_AMOUNT_MUST_POSITIVE("메뉴의 수량은 0보다 큰 값이어야 합니다."), | ||
| NO_INPUT_FOUNDED("입력이 존재하지 않습니다."), | ||
| ; | ||
|
|
||
| private static final String PREFIX = "[ERROR] "; | ||
| private final String messsage; | ||
|
|
||
| VendingMachineException(String messsage) { | ||
| this.messsage = messsage; | ||
| } | ||
|
|
||
| public String getMesssage() { | ||
| return PREFIX + messsage; | ||
| } | ||
|
|
||
| public IllegalArgumentException makeException(){ | ||
| return new IllegalArgumentException(getMesssage()); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
혁수님! OutputView를 static으로 불러올 수도 있고 객체를 만들어서 컨트롤러로 주입해줄 수 있는데 혹시 그중에 static을 사용하신 이유가 궁금해요
스터디때 최대한 static 사용을 지양하려고 고민 중이다! 라고 들었던 것 같아서 여쭤봅니당 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
우선
static import를 하지 않은 이유는 스터디때 말씀 드린것과 마찬가지로 해당 메서드의 위치를 확실하게 명시하는 것이 저의 취향이기 때문이에요 ㅎㅎ또, 의존성 주입을 사용하지 않은 것은 해당 부분에 대한 변경 가능성 없었기 때문입니다.
5시간이라는 짧은 시간동안 기능을 모두 완성하기 위해선 특정 부분에서는 트레이드 오프가 존재할 수 밖에 없다고 생각하는데 저에겐 이 부분이 트레이드 오프에 해당했어요.
만약
Randoms를 사용하는 클래스와 같이 테스트 과정에서 다른 클래스로 변경될 가능성이 있다면 의존성을 주입받았을 텐데요. 하지만 이번의 경우 출력을 하는View를 변경할 일이 적어도 5시간 내에는 존재하지 않았기 때문에 의존성 주입을 사용하지 않았습니다.마지막으로
OutputView의 메서드를static으로 만든 것은 실제 웹 MVC에서도 View에 해당하는 html은 정적 파일이기에 그와 비슷하게 구현해 보자는 생각 때문이었습니다.다만, 뭔가 이 부분이 원래 제가 사용하던 방법과 달라지다 보니 어색한 감이 있어 앞으론
OutputView도 하나의 객체로 생성하고 메서드를 호출할 것 같긴 해요!!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아 그러면 마지막에 말씀하신 내용은
으로 Controller에서
InputView inputView = new InputView()와 같이객체를 선언해서 사용하겠다는 말씀일까요?? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네, 지금은 그게 제일 저한테 익숙한 방법이라서요!