-
-
- First input
- A, 1:3, 2:3, 3:1
- B, 2:3, 3:2
- C, 3:5
- Second input
- D, 1:5
- E, 2:1, 3:1
- F, 1:1, 2:2
- Third input
- G, 3:3
- H, 3:1
- Fourth input
- I, 2:2
- First input
-
- 주문 담당자(Cashier)는 음료 주문을 연속해서 받을 수 있다.
- 음료 주문을 받으면 주문 대기표(Queue)에 추가한다.
- ✔ Drink < Order < OrderInfo -> Event
- ✔ EventQueue 를 통해 Event 를 전달한다
- 주문 대기표도 이벤트를 받아서 처리하는 별도 모듈/객체로 분리해서 구현한다.
- ✔ OrderSheet
- 매니저(Manager)는 음료를 확인하기 위해서 주문 대기표를 1초마다 확인한다.
- 주문이 있을 경우 작업이 비어있는 (제작할 수 있는) 바리스타에게 작업 이벤트를 전달한다.
- ❗ 주문을 먼저 특정 바리스타에게 할당, 해당 바리스타가 여유가 있을 때 제조 시작
- 바리스타가 보낸 특정 고객의 음료 제작 완료 이벤트를 받으면 결과를 출력한다.
- ✔ Publisher, Subscriber 패턴으로 구현
- 바리스타(Barista)는 동시에 2개까지 음료를 만들 수 있다고 가정한다.
- 스레드를 직접 생성하는 게 아니라 이벤트 방식으로 동작해야 한다.
- 바리스타는 음료를 만들기 시작할 때와 끝날 때 마다 이벤트를 발생한다.
- 이벤트가 발생할 때마다 음료 작업에 대한 로그를 출력한다.
- 프로그램을 시작할 때 바리스타 인원수를 결정할 수 있도록 구현한다.
- 프로그램이 시작하면 바리스타가 몇 명인지 출력한다.
- 주문 담당자와 매니저는 각각 1명이라고 가정한다.
- 주문 담당자는 음료 주문을 받을 때마다 한꺼번에 주문한 고객을 구분해야 한다.
- 매니저는 바리스타가 보낸 음료 작업 완료 이벤트를 받아서 고객별로 주문 완성표를 업데이트한다.
- ✔ OrderSheet 클래스의 markOrder 메서드
- 현황판에는 주문한 고객별로 주문한 음료를 모두 구분해서 표시해야 한다.
- 주문부터 제작 완료까지 이벤트 흐름을 그림으로 그려서, gist에 함께 첨부한다.
- 앞 단계에 이어서 각 언어와 플랫폼에서 제공하는 비동기 이벤트 처리 방식을 활용한다
- 주문 담당자 / 주문대기큐 / 매니저 / 바리스타 / 현황판과 주문 음료, 완성 음료에 대한 모듈 또는 파일을 구분해서 작업한다
- 고객이 주문한 모든 음료가 완성되면 각자 자기만의 방식으로 특별하게(?) 표시해서 출력한다.
- 모든 음료수를 만들고 나서 3초 동안 주문이 없으면 프로그램을 종료한다. (😢 미흡)
- ❗ 특정 시간 동안 주문이 없으면 Timeout 을 발생시키는 로직과 현재 제조하고 있는 음료가 없음을 나타내는 변수의 동작이 분리되어있다.
-
- 바리스타가 3명 이상일 경우 특정 바리스타가 담당하는 음료수를 분배하는 방식을 구현한다. 모든 바리스타가 모든 음료수를 만들지 않아야 한다.
- ✔ BaristaGroup 으로 바리스타들을 관리한다
- ✔ 소속 바리스타 중 당장 음료를 제조할 수 있는 타겟을 설정하여 주문을 알린다
- 바리스타 4명, 주문 고객 9명 + 음료 30개를 주문했다고 가정하고 동작을 확인한다.
- 바리스타가 3명 이상일 경우 특정 바리스타가 담당하는 음료수를 분배하는 방식을 구현한다. 모든 바리스타가 모든 음료수를 만들지 않아야 한다.
-
Week1-1.C__Users_rmtlr_CodeMasters_Week4_Cafe_README.md.2022-02-03.04-23-38.mp4
-
-
Save naneun/0207d6b17e3fd2fd3f73af06e1c3439b to your computer and use it in GitHub Desktop.
CS08
This file contains 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
package com.my.cs08.cafe.staff; | |
import com.my.cs08.order.Drink; | |
import com.my.cs08.util.OutputView; | |
import java.util.concurrent.*; | |
import java.util.concurrent.atomic.AtomicInteger; | |
public class Barista implements Comparable<Barista> { | |
private static final int MAX_WORKLOAD = 2; | |
private int id; | |
private OutputView outputView; | |
private AtomicInteger workload; | |
private ExecutorService executor; | |
public Barista(int id) { | |
this.id = id; | |
this.outputView = OutputView.getInstance(); | |
this.workload = new AtomicInteger(); | |
this.executor = Executors.newFixedThreadPool(MAX_WORKLOAD); /* Maximum 2 Tasks */ | |
} | |
public synchronized boolean afford() { | |
return workload.get() < MAX_WORKLOAD; | |
} | |
public void make(Drink drink) { | |
CompletableFuture.runAsync(() -> doing(drink), executor) | |
.exceptionally(ex -> { | |
outputView.errMsg(ex); | |
return null; | |
}) | |
.join(); | |
} | |
private void doing(Drink drink) { | |
try { | |
outputView.doingMsg(id, drink); | |
workload.set(workload.get() + 1); | |
TimeUnit.SECONDS.sleep(drink.getTime()); | |
outputView.doneMsg(id, drink); | |
workload.set(workload.get() - 1); | |
} catch (InterruptedException e) { | |
throw new CompletionException(e); | |
} | |
} | |
@Override | |
public int compareTo(Barista o) { | |
return Integer.compare(this.workload.get(), o.workload.get()); | |
} | |
} |
This file contains 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
package com.my.cs08.cafe.staff; | |
import com.my.cs08.cafe.role.Publisher; | |
import com.my.cs08.cafe.role.Subscriber; | |
import com.my.cs08.event.Event; | |
import com.my.cs08.util.OutputView; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.List; | |
import java.util.concurrent.CompletableFuture; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
public class BaristaGroup implements Publisher<Event>, Subscriber<Event> { | |
private OutputView outputView; | |
private List<Subscriber> subscribers; | |
private List<Barista> baristas; | |
private ExecutorService executor; | |
public BaristaGroup(int count) { | |
this.outputView = OutputView.getInstance(); | |
this.subscribers = new ArrayList<>(); | |
this.baristas = new ArrayList<>(); | |
for (int idx = 0; idx < count; ++idx) { | |
this.baristas.add(new Barista(idx + 1)); | |
} | |
this.executor = Executors.newFixedThreadPool(count); | |
} | |
@Override | |
public void subscribe(Subscriber<? super Event> subscriber) { | |
subscribers.add(subscriber); | |
} | |
public void notifyAllSubscribers(Event event) { | |
subscribers.forEach(subscriber -> { | |
subscriber.onNext(event); | |
}); | |
} | |
@Override | |
public void onNext(Event event) { | |
makeDrinkAsync(event); | |
} | |
private void makeDrinkAsync(Event event) { | |
CompletableFuture.supplyAsync(() -> { | |
Barista barista = null; | |
while (!(barista = assign()).afford()); | |
barista.make(event.getOrder().getDrink()); | |
return event; | |
}, executor) | |
.thenAccept((result) -> { | |
notifyAllSubscribers(result); | |
}) | |
.exceptionally(ex -> { | |
outputView.errMsg(ex); | |
return null; | |
}); | |
} | |
private Barista assign() { | |
return baristas.stream().sorted().findFirst().get(); | |
} | |
} |
This file contains 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
package com.my.cs08.cafe; | |
import com.my.cs08.cafe.staff.BaristaGroup; | |
import com.my.cs08.cafe.staff.Cashier; | |
import com.my.cs08.cafe.staff.Manager; | |
import com.my.cs08.event.EventQueue; | |
import com.my.cs08.order.OrderSheet; | |
import com.my.cs08.util.InputView; | |
import java.io.IOException; | |
import java.util.concurrent.atomic.AtomicBoolean; | |
public class Cafe { | |
public static AtomicBoolean isOpen; | |
public static AtomicBoolean inProgress; | |
private InputView inputView; | |
private Cashier cashier; | |
private Manager manager; | |
private BaristaGroup baristaGroup; | |
private OrderSheet orderSheet; | |
private EventQueue eventQueue; | |
public Cafe() throws IOException { | |
this.isOpen = new AtomicBoolean(false); | |
this.inputView = InputView.getInstance(); | |
this.inProgress = new AtomicBoolean(false); | |
this.orderSheet = new OrderSheet(); | |
this.eventQueue = new EventQueue(); | |
this.cashier = new Cashier(orderSheet, eventQueue); | |
this.manager = new Manager(orderSheet, eventQueue); | |
this.baristaGroup = new BaristaGroup(inputView.getBaristaCount()); | |
} | |
public void open() { | |
isOpen.set(true); | |
cashier.takeOrderAsync(); | |
manager.subscribe(baristaGroup); | |
manager.checkOrderAsync(); | |
baristaGroup.subscribe(manager); | |
} | |
} |
This file contains 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
package com.my.cs08.cafe.staff; | |
import com.my.cs08.cafe.Cafe; | |
import com.my.cs08.event.EventQueue; | |
import com.my.cs08.order.OrderInfo; | |
import com.my.cs08.order.OrderSheet; | |
import com.my.cs08.util.InputView; | |
import com.my.cs08.util.OutputView; | |
import java.util.concurrent.*; | |
public class Cashier { | |
private static final int TIMEOUT = 10; | |
private InputView inputView; | |
private OutputView outputView; | |
private OrderSheet orderSheet; | |
private EventQueue eventQueue; | |
private ExecutorService executor; | |
public Cashier(OrderSheet orderSheet, EventQueue eventQueue) { | |
this.inputView = InputView.getInstance(); | |
this.outputView = OutputView.getInstance(); | |
this.orderSheet = orderSheet; | |
this.eventQueue = eventQueue; | |
this.executor = Executors.newFixedThreadPool(1); | |
} | |
public void takeOrderAsync() { | |
CompletableFuture.runAsync(this::takeOrder); | |
} | |
private void takeOrder() { | |
while (Cafe.isOpen.get()) { | |
CompletableFuture.supplyAsync(this::takeInput, executor) | |
.orTimeout(TIMEOUT, TimeUnit.SECONDS) | |
.thenAccept(this::sendOrderInfo) | |
.exceptionally(this::exceptionCheck) | |
.join(); | |
} | |
executor.shutdown(); | |
outputView.closeMsg(); | |
} | |
private OrderInfo takeInput() { | |
try { | |
inputView.commandInfo(); | |
OrderInfo orderInfo = inputView.parsing(inputView.commandLine()); | |
Cafe.inProgress.set(true); | |
return orderInfo; | |
} catch (Exception ex) { | |
throw new CompletionException(ex); | |
} | |
} | |
private void sendOrderInfo(OrderInfo orderInfo) { | |
orderSheet.addOrder(orderInfo); | |
orderInfo.convertToEvents().forEach(event -> eventQueue.add(event)); | |
}; | |
private Void exceptionCheck(Throwable ex) { | |
Throwable tb = ex.getCause(); | |
if (tb instanceof TimeoutException && !Cafe.inProgress.get()) { | |
Cafe.isOpen.set(false); | |
} | |
if (!(tb instanceof TimeoutException)) { | |
outputView.errMsg(tb); | |
} | |
return null; | |
}; | |
} |
This file contains 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
package com.my.cs08.order; | |
public class Drink { | |
private int id; | |
private String name; | |
private int time; | |
public Drink(int id, String name, int time) { | |
this.id = id; | |
this.name = name; | |
this.time = time; | |
} | |
public static Drink getInstance(int id) { | |
return id == 1 ? new Drink(1, "Americano", 3) | |
: id == 2 ? new Drink(2, "CafeLatte", 5) | |
: new Drink(3, "Frappuccino", 10); | |
} | |
public int getId() { | |
return id; | |
} | |
public String getName() { | |
return name; | |
} | |
public int getTime() { | |
return time; | |
} | |
@Override | |
public String toString() { | |
return "Drink{" + | |
"id=" + id + | |
", name='" + name + '\'' + | |
", time=" + time + | |
'}'; | |
} | |
} |
This file contains 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
package com.my.cs08.event; | |
import com.my.cs08.order.Order; | |
public class Event { | |
private String customer; | |
private Order order; | |
public Event(String customer, Order order) { | |
this.customer = customer; | |
this.order = order; | |
} | |
public String getCustomer() { | |
return customer; | |
} | |
public Order getOrder() { | |
return order; | |
} | |
@Override | |
public String toString() { | |
return customer + order.getDrink().getId(); | |
} | |
} |
This file contains 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
package com.my.cs08.event; | |
import java.util.concurrent.LinkedBlockingQueue; | |
public class EventQueue { | |
private LinkedBlockingQueue<Event> queue; | |
public EventQueue() { | |
this.queue = new LinkedBlockingQueue<>(); | |
} | |
public Event poll() { | |
return queue.poll(); | |
} | |
public Event take() throws InterruptedException { | |
return queue.take(); | |
} | |
public void add(Event event) { | |
queue.add(event); | |
} | |
public void showElements() { | |
if (isEmpty()) { | |
return; | |
} | |
System.out.println(queue); | |
} | |
public boolean isEmpty() { | |
return queue.isEmpty(); | |
} | |
} |
This file contains 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
package com.my.cs08.util; | |
import com.my.cs08.order.OrderInfo; | |
import java.io.*; | |
public class InputView { | |
private static InputView inputView; | |
private Parser parser; | |
private BufferedReader br; | |
private InputView() { | |
this.parser = Parser.getInstance(); | |
this.br = new BufferedReader(new InputStreamReader(System.in)); | |
} | |
public static InputView getInstance() { | |
if (inputView == null) { | |
inputView = new InputView(); | |
} | |
return inputView; | |
} | |
public String commandLine() throws IOException { | |
return br.readLine(); | |
} | |
public int getBaristaCount() throws IOException { | |
System.out.print("> 바리스타 총 인원 수: "); | |
int count = Integer.parseInt(commandLine()); | |
System.out.println("> 바리스타는 총 " + count + "명입니다."); | |
return count; | |
} | |
public void commandInfo() { | |
System.out.println("> 메뉴 = 1. 아메리카노(3s) 2. 카페라떼(5s) 3. 프라프치노(10s)\n" + | |
"> 고객별로 주문할 음료 개수를 입력하세요. 예) A고객, 아메리카노 2개, 프라프치노 1개 => A, 1:2, 3:1"); | |
} | |
public OrderInfo parsing(String input) { | |
return parser.parsing(input); | |
} | |
} |
This file contains 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
package com.my.cs08; | |
import com.my.cs08.cafe.Cafe; | |
import java.io.IOException; | |
public class Main { | |
public static void main(String[] args) throws IOException { | |
Cafe cafe = new Cafe(); | |
cafe.open(); | |
} | |
} |
This file contains 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
package com.my.cs08.cafe.staff; | |
import com.my.cs08.cafe.Cafe; | |
import com.my.cs08.cafe.role.Publisher; | |
import com.my.cs08.cafe.role.Subscriber; | |
import com.my.cs08.event.Event; | |
import com.my.cs08.event.EventQueue; | |
import com.my.cs08.order.OrderSheet; | |
import com.my.cs08.util.OutputView; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.ScheduledExecutorService; | |
import java.util.concurrent.TimeUnit; | |
public class Manager implements Publisher<Event>, Subscriber<Event> { | |
private static final int CORE_POOL_SIZE = 1; | |
private static final int INITIAL_DELAY = 0; | |
private static final int PERIOD = 1; | |
private OutputView outputView; | |
private List<Subscriber> subscribers; | |
private OrderSheet orderSheet; | |
private EventQueue eventQueue; | |
private ScheduledExecutorService scheduledExecutor; | |
public Manager(OrderSheet orderSheet, EventQueue eventQueue) { | |
this.outputView = OutputView.getInstance(); | |
this.subscribers = new ArrayList<>(); | |
this.orderSheet = orderSheet; | |
this.eventQueue = eventQueue; | |
this.scheduledExecutor = Executors.newScheduledThreadPool(CORE_POOL_SIZE); | |
} | |
@Override | |
public void subscribe(Subscriber<? super Event> subscriber) { | |
subscribers.add(subscriber); | |
} | |
@Override | |
public void onNext(Event event) { | |
String customer = event.getCustomer(); | |
orderSheet.markOrder(event); | |
if (orderSheet.readyOrder(customer)) { | |
outputView.readyMsg(customer, orderSheet.getOrderList(customer)); | |
orderSheet.clearOrder(customer); | |
if (orderSheet.noMoreOrder()) { | |
Cafe.inProgress.set(false); | |
} | |
} | |
} | |
public void checkOrderAsync() { | |
scheduledExecutor.scheduleAtFixedRate(this::checkOrder | |
, INITIAL_DELAY, PERIOD, TimeUnit.SECONDS); | |
} | |
private void checkOrder() { | |
if (!eventQueue.isEmpty()) { | |
outputView.QueueState(eventQueue); | |
Event event = eventQueue.poll(); | |
notifyBaristaGroup(event); | |
} | |
} | |
private void notifyBaristaGroup(Event event) { | |
subscribers.forEach((subscriber -> { | |
subscriber.onNext(event); | |
})); | |
} | |
} |
This file contains 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
package com.my.cs08.order; | |
public class Order { | |
private Drink drink; | |
private int count; | |
public Order(int id, int count) { | |
this.drink = Drink.getInstance(id); | |
this.count = count; | |
} | |
public Drink getDrink() { | |
return drink; | |
} | |
public int getCount() { | |
return count; | |
} | |
@Override | |
public String toString() { | |
return "Order{" + | |
"drink=" + drink + | |
", count=" + count + | |
'}'; | |
} | |
} |
This file contains 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
package com.my.cs08.order; | |
import com.my.cs08.event.Event; | |
import java.util.ArrayList; | |
import java.util.List; | |
public class OrderInfo { | |
private String customer; | |
private List<Order> orders; | |
public OrderInfo(String customer, List<Order> orders) { | |
this.customer = customer; | |
this.orders = orders; | |
} | |
public String getCustomer() { | |
return customer; | |
} | |
public List<Order> getOrders() { | |
return orders; | |
} | |
public List<Event> convertToEvents() { | |
List<Event> events = new ArrayList<>(); | |
orders.forEach(order -> { | |
int count = order.getCount(); | |
while (count-- > 0) { | |
events.add(new Event(customer, order)); | |
} | |
}); | |
return events; | |
} | |
@Override | |
public String toString() { | |
return "OrderInfo{" + | |
"customer='" + customer + '\'' + | |
", orders=" + orders + | |
'}'; | |
} | |
} |
This file contains 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
package com.my.cs08.order; | |
import com.my.cs08.cafe.staff.Manager; | |
import com.my.cs08.event.Event; | |
import java.util.*; | |
public class OrderSheet { | |
private Map<String, List<Order>> sheet; | |
private Map<String, Map<String, Integer>> orderMap; | |
public OrderSheet() { | |
this.sheet = new HashMap<>(); | |
this.orderMap = new HashMap<>(); | |
} | |
public List<Order> getOrderList(String customer) { | |
return sheet.get(customer); | |
} | |
public void addOrder(OrderInfo orderInfo) { | |
String customer = orderInfo.getCustomer(); | |
List<Order> orders = orderInfo.getOrders(); | |
sheet.put(customer, orders); | |
orderMap.put(customer, new HashMap<>()); | |
Map<String, Integer> mp = orderMap.get(customer); | |
orders.forEach(order -> { | |
String str = customer + order.getDrink().getId(); | |
if (!mp.containsKey(str)) { | |
mp.put(str, 0); | |
} | |
mp.put(str, mp.get(str) + order.getCount()); | |
}); | |
} | |
public void markOrder(Event event) { | |
String customer = event.getCustomer(); | |
Map<String, Integer> mp = orderMap.get(customer); | |
String str = customer + event.getOrder().getDrink().getId(); | |
mp.put(str, mp.get(str) - 1); | |
if (mp.get(str) == 0) { | |
mp.remove(str); | |
} | |
} | |
public boolean readyOrder(String customer) { | |
return orderMap.get(customer).size() == 0; | |
} | |
public void clearOrder(String customer) { | |
orderMap.remove(customer); | |
} | |
public boolean noMoreOrder() { | |
return orderMap.size() == 0; | |
} | |
} |
This file contains 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
package com.my.cs08.util; | |
import com.my.cs08.event.EventQueue; | |
import com.my.cs08.order.Drink; | |
import com.my.cs08.order.Order; | |
import com.my.cs08.order.OrderSheet; | |
import java.util.List; | |
public class OutputView extends OrderSheet { | |
private static OutputView outputView; | |
private OutputView() {} | |
public static OutputView getInstance() { | |
if (outputView == null) { | |
outputView = new OutputView(); | |
} | |
return outputView; | |
} | |
public void QueueState(EventQueue eventQueue) { | |
eventQueue.showElements(); | |
} | |
public void doingMsg(int id, Drink drink) { | |
System.out.println("Barista" + id + " - " + drink.getName() + " in the making"); | |
} | |
public void doneMsg(int id, Drink drink) { | |
System.out.println("Barista" + id + " - " + drink.getName() + " completion"); | |
} | |
public void errMsg(Throwable ex) { | |
System.out.println(ex); | |
} | |
public void readyMsg(String customer, List<Order> orderList) { | |
String info = orderList.stream().map(order -> | |
String.format("%s * %d, ", order.getDrink().getName(), order.getCount())) | |
.reduce(": ", (a, b) -> a + b); | |
System.out.println(customer + info.substring(0, info.length() - 2)); | |
} | |
public void closeMsg() { | |
System.out.println("Cafe is closed and no longer accepting orders"); | |
} | |
} |
This file contains 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
package com.my.cs08.util; | |
import com.my.cs08.order.Order; | |
import com.my.cs08.order.OrderInfo; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.regex.Matcher; | |
import java.util.regex.Pattern; | |
public class Parser { | |
private static Parser parser; | |
private Parser() {} | |
public static Parser getInstance() { | |
if (parser == null) { | |
parser = new Parser(); | |
} | |
return parser; | |
} | |
private boolean isValid(String input) { | |
Pattern pattern = Pattern.compile("[A-Z], \\d+:\\d+(, \\d+:\\d+)*"); | |
Matcher matcher = pattern.matcher(input); | |
return matcher.matches(); | |
} | |
public OrderInfo parsing(String input) throws IllegalArgumentException { | |
if (!isValid(input)) { | |
throw new IllegalArgumentException("Invalid input"); | |
} | |
Pattern pattern = Pattern.compile("[A-Z]"); | |
Matcher matcher = pattern.matcher(input); | |
if (!matcher.find()) { | |
throw new IllegalArgumentException("Invalid input"); | |
} | |
String customer = matcher.group(); | |
pattern = Pattern.compile("\\d+:\\d+"); | |
matcher = pattern.matcher(input); | |
int elements = 0; | |
while (matcher.find()) { | |
++elements; | |
} | |
pattern = Pattern.compile("\\d+"); | |
matcher = pattern.matcher(input); | |
List<Order> orders = new ArrayList<>(); | |
int id, count; | |
for (int i = 0; i < elements; ++i) { | |
if (!matcher.find()) { | |
throw new IllegalArgumentException("Invalid input"); | |
} | |
id = Integer.parseInt(matcher.group()); | |
if (!matcher.find()) { | |
throw new IllegalArgumentException("Invalid input"); | |
} | |
count = Integer.parseInt(matcher.group()); | |
orders.add(new Order(id, count)); | |
} | |
return new OrderInfo(customer, orders); | |
} | |
} |
This file contains 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
package com.my.cs08.cafe.role; | |
public interface Publisher<T> { | |
void subscribe(Subscriber<? super T> subscriber); | |
} |
This file contains 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
package com.my.cs08.cafe.role; | |
public interface Subscriber<T> { | |
void onNext(T t); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment