[JAVA] 자판기 만들기 실습
오늘은 하나의 클래스 안에서 자판기를 구현하는 방법을 공부해보려고 한다.
[ 설계서 ]
- Product 클래스 [ VO, DAO 역할 ]
우선 만들 자판기의 기능을 크게 두가지로 나누면
- 사용자 모드
- 관리자 모드
위와 같이 두가지의 기능으로 분류하고 사용자 모드에는
- 상품 목록 출력
- 상품 구매
두개의 기능을 구현할 예정이고, 관리자 모드에서는
- 상품 추가
- 상품 재고 변경
- 상품 삭제
이렇게 3가지 기능을 구현할 예정이다.
멤버 변수로는
- 상품 PK
- 이름
- 가격
- 재고량
을 선언할 예정이고, 외부 class에서 접근할 수 없도록 private로 선언한다. 또한 외부 클래스에서 사용하기 위해서 getter, setter도 같이 생성할 예정이다.
생성자로는 멤버변수 4가지를 모두 main()에서 입력받을 것이기 때문에, 매개 변수로 생성할 예정이다.
기능을 구현할 메소드로는
- sell() [ 판매 출력 및 현재 재고량 - 사용자의 입력값을 연산하기 위한 메소드 (매개변수로는 사용자의 입력값인 count 입력 값을 넣을 예정 ]
- changeProduct() [ 재고 변경 메소드, 현재 재고량 + 사용자의 입력값을 연산하기 위한 메소드 (매개변수로는 사용자의 입력값인 productStock을 넣을 예정 ]
- toString() 재정의(오버라이딩) [상품 목록 출력시 재고량이 0일 경우 품절, 그게 아니라면 현재 재고량을 보여주기 위한 재정의 ]
- main()
먼저, 상품이 어떤것이 얼만큼 생성될지 모르기 때문에 배열리스트인 ArrayList를 사용할 예정
[ ArrayList<Product> data = new ArrayList<Product>(); ]
상품은 모두 고유한 상품번호를 가지고 있기 때문에 PK를 설정해 줄 예정
[ int numPK = 1 ] --> 상품의 번호는 1부터 시작
사용자의 입력 값을 저장하기 위한 변수 action을 선언 -> 사용자의 입력값에 따른 로직으로 구성할 예정
[ int action ]
프로그램은 종료 버튼을 누르기 전까지 종료하지 않을 예정이므로, while(true)를 통해 무한루프를 돌릴 예정
그에 따른 종료 조건은 제일 밑의 메뉴인 '3'번에 '프로그램 종료' 버튼을 만들 예정
사용자 모드
- 사용자의 입력값이 '1' 일 경우 [ 상품 목록 출력 ]
- 사용자의 입력값이 '2'일 경우 [ 상품 구매 ]
- 사용자의 입력값이 '3'일 경우 [ 프로그램 종료 ]
관리자 모드 [ 사용자모드에서 사용자의 입력값이 '1234'일 경우로 설정 ]
- 관리자의 입력값이 '1'일 경우 [ 상품 추가 ]
- 관리자의 입력값이 '2'일 경우 [ 상품 재고 변경 ]
- 관리자의 입력값이 '3'일 경우 [ 상품 삭제 ]
- 관리자의 입력값이 '4'일 경우 [ 관리자 모드 종료 및 사용자 모드 활성화 ]
[ 코드 구현 ]
Product 클래스
class Product {
private int productNum; // PK
private String productName; // 상품 이름
private int productPrice; // 상품 가격
private int productStock; // 상품 재고
// 생성자 ===========================================================================================
Product(int productNum, String productName, int productPrice, int productStock) { // 4가지 모두 입력받을 예정
this.productNum = productNum;
this.productName = productName;
this.productPrice = productPrice;
this.productStock = productStock;
}
// 구현 메소드 ===========================================================================================
// [상품 구매]
void sell(int count) {
System.out.println(this.productName + "상품은 " + count + "개 구매 완료 !");
this.productStock -= count; // 재고에서 구매한 만큼의 개수 빼기
}
// [ 재고 변경]
void changeProduct(int productStock) {
System.out.print(this.productName + "상품은 " + this.productStock + "개에서 "); // 이전 재고 개수
this.productStock += productStock; // 재고 개수가 추가된 만큼 더해줌
System.out.println(this.productStock + " 으로 변경되었습니다."); // 변경된 재고 개수
}
// toString() 재정의 ===========================================================================================
@Override
public String toString() { // toString 재정의하여 상품 목록 출력 메뉴 사용 시 출력
if (this.productStock == 0) { // 재고가 0개라면
return this.productNum + ". " + this.productName + " : " + this.productPrice + "[품절]"; // 품절 출력
}
return this.productNum + ". " + this.productName + " : " + this.productPrice + "[" + this.productStock + "]";
}
// getter & setter ===========================================================================================
public int getProductNum() {
return productNum;
}
public void setProductNum(int productNum) {
this.productNum = productNum;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public int getProductPrice() {
return productPrice;
}
public void setProductPrice(int productPrice) {
this.productPrice = productPrice;
}
public int getProductStock() {
return productStock;
}
public void setProductStock(int productStock) {
this.productStock = productStock;
}
}
main()
선언부
public class Test01 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList<Product> data = new ArrayList<Product>(); // Product 클래스 객체 생성
int numPk = 1; // 상품의 번호는 1부터 시작
int action; // 사용자의 메뉴 번호 입력값을 저장할 변수
위의 설계서와 같이 리스트배열과 PK, action 변수 선언과 입력을 하기 위한 Scanner 함수 생성
구현부
사용자 메뉴 출력 및 무한 반복문 ( + 종료 조건 )
// 첫 화면
System.out.println("==============");
System.out.println("1. 상품 목록 출력");
System.out.println("2. 구매하기");
System.out.println("3. 프로그램 종료");
System.out.println("==============");
System.out.println();
System.out.print("사용할 메뉴를 선택하세요. ");
action = sc.nextInt(); // 사용자의 입력
while (true) { // 프로그램이 종료되지 않도록 무한 반복
if (action == 3) { // 3. 프로그램종료
System.out.println("프로그램을 종료합니다.");
System.out.println();
break;
}
처음 코드 : 사용자 모드 메뉴 1번 ( 상품 목록 출력 ) + 처음 toString() 재정의
@Override
public String toString() { // toString 재정의하여 상품 목록 출력 메뉴 사용 시 출력
return this.productNum + ". " + this.productName + " : " + this.productPrice + "[" + this.productStock + "]";
}
...
else if (action == 1) { // 1. 상품목록출력 (재고없는상품은 [품절])
System.out.println("=== 상품 목록 ===");
for (Product product : data) { // ArrayList에 저장된 값들을 출력하기 위해 forEach문 사용
System.out.println(product); // 저장된 값들 출력
}
System.out.println("상품 출력 완료 ! 메뉴로 돌아갑니다.");
System.out.println();
}
위와 같이 재정의 후 출력을 할 경우에 재고가 0인 경우 [품절] 로 뜨지 않고, 0으로 뜨는 것을 알게 되었고 아래와 같이 수정해 보았다.
수정 [toString() if문 추가]
@Override
public String toString() { // toString 재정의하여 상품 목록 출력 메뉴 사용 시 출력
// 수정 부분 [if 조건문]
if(this.productStock == 0) {
return this.productNum + ". " + this.productName + " : " + this.productPrice + "[ 품절 ]";
}
return this.productNum + ". " + this.productName + " : " + this.productPrice + "[" + this.productStock + "]";
}
...
else if (action == 1) { // 1. 상품목록출력 (재고없는상품은 [품절])
System.out.println("=== 상품 목록 ===");
for (Product product : data) { // ArrayList에 저장된 값들을 출력하기 위해 forEach문 사용
System.out.println(product); // 저장된 값들 출력
}
System.out.println("상품 출력 완료 ! 메뉴로 돌아갑니다.");
System.out.println();
}
2. 상품 구매
class Product {
...
// [ 상품 구매 메소드]
void sell(int count) {
System.out.println(this.productName + "상품은 " + count + "개 구매 완료 !");
this.productStock -= count; // 재고에서 구매한 만큼의 개수 빼기
}
...
}
...
else if (action == 2) { // 2. 구매하기
System.out.println("=== 상품 목록 ===");
for (Product product : data) { // 사용자가 구매를 눌렀을 시 메뉴를 보기 편하도록 상품 목록 출력
System.out.println(product);
}
int cnt = 0; // 구매할 개수 0으로 초기화
while (true) {
System.out.println();
System.out.print("구매할 상품의 번호를 입력하세요. ");
int num = sc.nextInt();
System.out.println(data.get(i)); // 사용자가 입력한 상품
System.out.println("위 상품을 구매하시겠습니까 ? ");
System.out.println("1. Yes 2. No ");
System.out.print("번호 입력) ");
int isTrue = sc.nextInt();
if (isTrue == 1) { // 상품을 구매하겠다면
System.out.print("상품의 개수를 구매하실 만큼 입력하세요. ");
cnt = sc.nextInt();
int total = data.get(i).getProductPrice() * cnt; // 총 가격 연산
System.out.println("상품의 개수는 " + cnt + "개이고, 가격은 " + total + "원 입니다.");
System.out.println("1. 구매하기 2. 구매하지 않기 ");
System.out.print("번호 입력) ");
int isBuy = sc.nextInt();
if (isBuy == 1) {
data.get(i).sell(cnt); // Product 클래스의 sell() 메소드 사용
break; // 이중 반복문 즉시 종료
} else if (isBuy == 2) {
System.out.println("구매하지 않아 메뉴로 돌아갑니다. ");
break; // 메뉴로 이동
}
} else if (isTrue == 2) {
System.out.println("구매하지 않아 메뉴로 돌아갑니다. ");
break;
}
}
}
}
상품 구매의 경우 사용자가 구매하려는 상품의 개수만큼 기존의 상품 재고량에서 빼주는 기능을 하는 메소드를 Product 클래스에서 따로 구현 및 출력을 하도록 설정해놓았다.
관리자 모드 진입 및 메뉴 ( + 종료 조건)
} else if (action == 1234) { // 관리자 모드 접근
while (true) { // 관리자 모드 진입
String name; // 입력 받을 이름 변수
int price; // 입력 받을 가격 변수
int stock; // 입력 받을 재고 변수
System.out.println("관리자 프로그램을 실행합니다.");
System.out.println();
System.out.println("=== 관리자 프로그램 ===");
System.out.println("1. 상품 추가");
System.out.println("2. 상품 재고 변경");
System.out.println("3. 상품 삭제");
System.out.println("4. 관리자 프로그램 종료");
System.out.println();
System.out.print("사용할 메뉴를 선택해주세요. ");
int action2 = sc.nextInt();
if (action2 == 4) { // 4. 관리자모드종료
System.out.println("사용자 프로그램으로 돌아갑니다.");
break;
}
...
관리자 모드 진입 방법을 사용자 메뉴의 입력 부분에서 1234를 입력 시 접근할 수 있도록 설정해놓았다. 또한, 무한 반복을 설정해 놓았으므로 종료조건( 사용자의 입력값이 '4' 일 경우 )도 같이 설정해놓은 것을 볼 수 있다.
3. 상품 추가
else if (action2 == 1) { // 1. 상품추가
System.out.print("추가할 상품의 이름을 입력하세요. ");
name = sc.next();
System.out.println(name + "으로 사용하시겠습니까 ? ");
System.out.print("1. Yes 2. No ");
System.out.print("상품의 가격을 입력하세요. ");
price = sc.nextInt();
System.out.print("상품의 재고를 입력하세요. ");
stock = sc.nextInt();
System.out.println(numPk + ". " + name + " " + price + "원 " + stock + "개 생성완료!"); // 가독성을 위해 출력
data.add(new Product(numPk++, name, price, stock)); // 입력받은 값 저장
}
사용자가 상품 추가를 눌렀다면, 추가할 상품의 이름, 가격, 재고량을 입력 받고 그것을 ArrayList<Product> data에 저장하는 기능을 구현해놓았다.
4. 상품 재고 변경
class Product {
...
// [ 재고 변경]
void changeProduct(int productStock) {
System.out.print(this.productName + "상품은 " + this.productStock + "개에서 "); // 이전 재고 개수
this.productStock += productStock; // 재고 개수가 추가된 만큼 더해줌
System.out.println(this.productStock + " 으로 변경되었습니다."); // 변경된 재고 개수
}
...
}
else if (action2 == 2) { // 2. 상품재고변경
System.out.println("=== 상품 목록 ===");
for (Product product : data) { // ArrayList에 저장된 값들을 출력하기 위해 forEach문 사용
System.out.println(product); // 저장된 값들 출력
}
System.out.println();
System.out.print("변경할 상품의 번호를 입력해주세요. ");
int num = sc.nextInt();
int i = 0;
while (i < data.size()) { // 지금까지 입력받은 값들이 있는 배열 리스트 안에
if (num == data.get(i).getProductNum()) { // 입력한 번호와 맞는 내 번호가 있니 ?
System.out.println(data.get(i).getProductName() + "상품의 재고를 변경합니다. "); // 입력할 번호에 있는
System.out.print("변경할 상품의 재고를 추가할만큼 입력해주세요. ");
stock = sc.nextInt();
data.get(i).changeProduct(stock); // 입력한 번호의 상품을 changeProduct()로 실행한다.
break;
}
}
}
상품 재고 변경을 입력하였다면, 상품의 번호를 사용자에게 입력받아 상품의 재고의 PK를 기존의 데이터에서 찾아 추가할 만큼 입력을 받고 위에 선언해 놓은 메소드를 호출하여 현재 재고량 + 사용자의 입력값을 하도록 구현해 놓았다. 또한 사용자의 편의성을 위해 출력문을 설정해놓았다.
5. 상품 삭제
else if (action2 == 3) { // 3. 상품삭제
int num;
System.out.print("삭제할 상품의 번호를 입력해주세요. ");
num = sc.nextInt();
for (int i = 0; i < data.size(); i++) { // 지금까지 입력받은 값들이 있는 배열 리스트 안에
if (num == data.get(i).getProductNum()) { // 혹시 지금 입력받은 번호가 배열 리스트에 있니 ?
System.out.println(data.get(i).getProductName() + "상품 삭제 완료! ");
data.remove(i); // 그번호의 상품 삭제하기
break;
}
}
}
상품 삭제를 입력하였다면, 삭제할 상품의 PK를 입력 받아 기존의 데이터를 통해 찾은 후 그 상품을 삭제하도록 설정하였다.
최종 코드
package test;
import java.util.ArrayList;
import java.util.Scanner;
// 상품 : PK,이름,가격,재고
// 판매()
// 재고변경()
// 관리자 모드 Password : 1234
class Product {
private int productNum; // PK
private String productName; // 상품 이름
private int productPrice; // 상품 가격
private int productStock; // 상품 재고
Product(int productNum, String productName, int productPrice, int productStock) { // 4가지 모두 입력받을 예정
this.productNum = productNum;
this.productName = productName;
this.productPrice = productPrice;
this.productStock = productStock;
}
void sell(int count) {
System.out.println(this.productName + "상품은 " + count + "개 구매 완료 !");
this.productStock -= count; // 재고에서 구매한 만큼의 개수 빼기
}
void changeProduct(int productStock) {
System.out.print(this.productName + "상품은 " + this.productStock + "개에서 "); // 이전 재고 개수
this.productStock += productStock; // 재고 개수가 추가된 만큼 더해줌
System.out.println(this.productStock + " 으로 변경되었습니다."); // 변경된 재고 개수
}
@Override
public String toString() { // toString 재정의하여 상품 목록 출력 메뉴 사용 시 출력
if (this.productStock == 0) { // 재고가 0개라면
return this.productNum + ". " + this.productName + " : " + this.productPrice + "[품절]"; // 품절 출력
}
return this.productNum + ". " + this.productName + " : " + this.productPrice + "[" + this.productStock + "]";
}
public int getProductNum() {
return productNum;
}
public void setProductNum(int productNum) {
this.productNum = productNum;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public int getProductPrice() {
return productPrice;
}
public void setProductPrice(int productPrice) {
this.productPrice = productPrice;
}
public int getProductStock() {
return productStock;
}
public void setProductStock(int productStock) {
this.productStock = productStock;
}
}
public class Test01 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList<Product> data = new ArrayList<Product>(); // Product 클래스 객체 생성
int numPk = 1; // 상품의 번호는 1부터 시작
int action; // 메뉴 번호 입력 변수
System.out.println("==============");
System.out.println("1. 상품 목록 출력");
System.out.println("2. 구매하기");
System.out.println("3. 프로그램 종료");
System.out.println("==============");
System.out.println();
System.out.print("사용할 메뉴를 선택하세요. ");
action = sc.nextInt();
while (true) {
if (action == 3) { // 3. 프로그램종료
System.out.println("프로그램을 종료합니다.");
System.out.println();
break;
} else if (action == 1) { // 1. 상품목록출력 (재고없는상품은 [품절])
System.out.println("=== 상품 목록 ===");
for (Product product : data) { // ArrayList에 저장된 값들을 출력하기 위해 forEach문 사용
System.out.println(product); // 저장된 값들 출력
}
System.out.println("상품 출력 완료 ! 메뉴로 돌아갑니다.");
System.out.println();
} else if (action == 2) { // 2. 구매하기
System.out.println("=== 상품 목록 ===");
for (Product product : data) { // 사용자가 구매를 눌렀을 시 메뉴를 보기 편하도록 상품 목록 출력
System.out.println(product);
}
int cnt = 0; // 구매할 개수 0으로 초기화
while (true) {
System.out.println();
System.out.print("구매할 상품의 번호를 입력하세요. ");
int num = sc.nextInt();
if (!(0 < num && num <= data.size())) {
System.out.println("잘못 입력 하셨습니다. 다시 입력해주세요.");
continue;
}
for (int i = 0; i < data.size(); i++) { // 지금까지 입력받은 값들이 있는 배열 리스트 안에
if (num == data.get(i).getProductNum()) { // 혹시 지금 입력받은 번호가 배열 리스트에 있니 ?
if (data.get(i).getProductStock() == 0) { // 혹시 재고가 0이라면
System.out.println("재고가 없어서 메뉴로 돌아갑니다.");
break;
} else {
System.out.println(data.get(i)); // 사용자가 입력한 상품
System.out.println("위 상품을 구매하시겠습니까 ? ");
System.out.println("1. Yes 2. No ");
System.out.print("번호 입력) ");
int isTrue = sc.nextInt();
if (isTrue == 1) { // 상품을 구매하겠다면
System.out.print("상품의 개수를 구매하실 만큼 입력하세요. ");
cnt = sc.nextInt();
int total = data.get(i).getProductPrice() * cnt; // 총 가격 연산
System.out.println("상품의 개수는 " + cnt + "개이고, 가격은 " + total + "원 입니다.");
System.out.println("1. 구매하기 2. 구매하지 않기 ");
System.out.print("번호 입력) ");
int isBuy = sc.nextInt();
if (isBuy == 1) {
data.get(i).sell(cnt); // Product 클래스의 sell() 메소드 사용
break; // 이중 반복문 즉시 종료
} else if (isBuy == 2) {
System.out.println("구매하지 않아 메뉴로 돌아갑니다. ");
break; // 메뉴로 이동
}
} else if (isTrue == 2) {
System.out.println("구매하지 않아 메뉴로 돌아갑니다. ");
break;
}
}
}
}
}
} else if (action == 1234) { // 관리자 모드 접근
while (true) { // 관리자 모드 진입
String name; // 입력 받을 이름 변수
int price; // 입력 받을 가격 변수
int stock; // 입력 받을 재고 변수
System.out.println("관리자 프로그램을 실행합니다.");
System.out.println();
System.out.println("=== 관리자 프로그램 ===");
System.out.println("1. 상품 추가");
System.out.println("2. 상품 재고 변경");
System.out.println("3. 상품 삭제");
System.out.println("4. 관리자 프로그램 종료");
System.out.println();
System.out.print("사용할 메뉴를 선택해주세요. ");
int action2 = sc.nextInt(); // 사용자의 입력값
if (action2 == 4) { // 4. 관리자모드종료
System.out.println("사용자 프로그램으로 돌아갑니다.");
break;
} else if (action2 == 1) { // 1. 상품추가
System.out.print("추가할 상품의 이름을 입력하세요. ");
name = sc.next();
System.out.println(name + "으로 사용하시겠습니까 ? ");
System.out.print("1. Yes 2. No ");
System.out.print("상품의 가격을 입력하세요. ");
price = sc.nextInt();
System.out.print("상품의 재고를 입력하세요. ");
stock = sc.nextInt();
System.out.println(numPk + ". " + name + " " + price + "원 " + stock + "개 생성완료!"); // 가독성을 위해 출력
data.add(new Product(numPk++, name, price, stock)); // 입력받은 값 저장
} else if (action2 == 2) { // 2. 상품재고변경
System.out.println("=== 상품 목록 ===");
for (Product product : data) { // ArrayList에 저장된 값들을 출력하기 위해 forEach문 사용
System.out.println(product); // 저장된 값들 출력
}
System.out.println();
System.out.print("변경할 상품의 번호를 입력해주세요. ");
int num = sc.nextInt();
int i = 0;
while (i < data.size()) { // 지금까지 입력받은 값들이 있는 배열 리스트 안에
if (num == data.get(i).getProductNum()) { // 입력한 번호와 맞는 내 번호가 있니 ?
System.out.println(data.get(i).getProductName() + "상품의 재고를 변경합니다. "); // 입력할 번호에 있는
System.out.print("변경할 상품의 재고를 추가할만큼 입력해주세요. ");
stock = sc.nextInt();
data.get(i).changeProduct(stock); // 입력한 번호의 상품을 changeProduct()로 실행한다.
break;
}
}
} else if (action2 == 3) { // 3. 상품삭제
int num;
System.out.print("삭제할 상품의 번호를 입력해주세요. ");
num = sc.nextInt();
for (int i = 0; i < data.size(); i++) { // 지금까지 입력받은 값들이 있는 배열 리스트 안에
if (num == data.get(i).getProductNum()) { // 혹시 지금 입력받은 번호가 배열 리스트에 있니 ?
System.out.println(data.get(i).getProductName() + "상품 삭제 완료! ");
data.remove(i); // 그번호의 상품 삭제하기
break;
}
}
}
}
}
}
}
}
다음 시간에는 유효성 검사 및 기능 검사를 추가로 포스팅할 예정이다.