열심히 끝까지

[코딩 과제] - 6/29 MVC 자판기 프로그램 + 관리자 프로그램 본문

디바이스 융합 자바(Java)기반 풀스택 개발자 양성과정(과제)

[코딩 과제] - 6/29 MVC 자판기 프로그램 + 관리자 프로그램

노유림 2022. 6. 29. 13:01

-----ProductView---

package view;
import java.util.ArrayList;
import java.util.Scanner;
import javax.sql.DataSource;
import javax.xml.crypto.Data;
import model.ProductVO;
public class ProductView {
	Scanner sc = new Scanner(System.in);
	public int action;
	public void startView() {
		while(true) { // 유효성 검사 -> 꼼꼼하게 작업해보기!
			System.out.println("=== 자판기 ===");
			System.out.println("1.메뉴확인 2.구매 3.종료");
			System.out.print("입력) ");
			action = sc.nextInt();
			if(action >= 1 && action <=3 || action == 1234) { // 관리자모드 1234
				break;
			}
			System.out.println("범위외입력!");
		}
	}
	public void manageView() {
		while(true) { // 관리자모드 입장!
			System.out.println("=== 관리자모드 ===");
			System.out.println("1.음료추가 2.음료재고추가 3.음료삭제 4.종료");
			System.out.print("입력) ");
			action = sc.nextInt();// 입력값
			if(action >= 1 && action <= 4) { // 입력값이 1~4면
				break; // 반복문 탈출!
			}
			System.out.println("범위외입력!");
		}
	}
	public void funcM1(ArrayList<ProductVO> datas) { // 추가할 음료와 가격
		System.out.print("추가할 음료와 가격을 입력하세요) ");
		String name = sc.next();
		int price = sc.nextInt();
	}
	public void func1(ArrayList<ProductVO> datas) {
		for(int i = 0; i < datas.size(); i++) {
			System.out.println((i+1)+"번 메뉴 " + datas.get(i).getName());
		}
	}
	public void func2(ArrayList<ProductVO> datas) {
		for(int i = 0; i < datas.size(); i++) {
			System.out.print((i+1)+"번 메뉴 " + datas.get(i).getName());
			if(datas.get(i).getCnt()==0) {
				System.out.println("x");
				continue;
			}
			System.out.println(datas.get(i).getCnt());
		}
		while(true) {
			System.out.print("메뉴 입력 ) ");
			action = sc.nextInt();
			if(1<=action && action <= datas.size()) {
				break;
			}
			System.out.println("상품번호 확인 후 다시 입력해주세요!");
		}
		// action += 100; -> Controller 에서 해야한다고 강사님은 생각!
		// 상품번호가 몇번인지 모르는게 맞기 때문에!
	}
	public void funcT(ProductVO vo) {
		System.out.println(vo.getName() + "구매완료!");
	}
	public void funcF(ProductVO vo) {
		System.out.println(vo.getName() + " 재고가 없습니다...");
	}
	public void func3() {
		System.out.println("프로그램이 종료됩니다");
		for(int i = 0; i < 5; i++) {
			System.out.println(".");
			try {
				Thread.sleep(1000); // 1000당 1초 재운다 == sleep
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
		}
	}
}

 

-----ProductController

package controller;
import model.ProductDAO;
import model.ProductVO;
import view.ProductView;
public class ProductController {
	ProductDAO model;
	ProductView view;
	public ProductController() {
		model = new ProductDAO();
		view = new ProductView();
	}
	public void startApp() {
		while(true) {
			view.startView();
			if(view.action==1) {
				view.func1(model.selectAll());
			}
			else if(view.action==2) {
				view.func2(model.selectAll());
				// 사용자가 먹고 싶은 메뉴의 번호를 입력햇는데,
				// C에서 [view.action]
				// C 에서는 사용자가 입력한 메뉴의 번호를 view.action으로 참조 가능하고,
				// M은 pk를 입력받으면 상품객체를 줄 준비가 되어있습니다.
				int num =view.action;// V에서 사용자가 입력한 메뉴 번호 pk 해당
				ProductVO vo = model.selectOne(num+ 100);
				// pk를 넣으면 해당하는 상품을 반환하는 M의 selectOne()메서드
				boolean flag = model.update(vo);
				// M은 반환받은(==사용자가 선택한) 객체의 재고를 --
				// boolean flag=model.update(model.selectOne(view.action+100)); // 상품객체 전달
				if(flag) {
					view.funcT(vo);
				}
				else {
					view.funcF(vo);
				}
			}
			else if(view.action==3) {
				view.func3();
				break;
			}
			else if(view.action == 1234) { // 관리자모드
				view.manageView(); // 관리자모드로 이동!
			}
		}
	}
}

 

 

------------강사님의 풀이----(직접 다시 해보기)
제일 중요한 것!!
    음료추가할 때, 이름, 가격, 재고 를 입력하는 것이 일반적
    이 이름, 가격, 재고를...
    음료를 만드는 메서드로 묶어버리면
    나중에 재고를 추가하는 기능을 한번 더 만들어야한다.
    한 줄만 뜰 수 있게 만들게 다 따로 만드는 것이 좋다!!

   웹개발에서는 음료 가격, 재고, 번호입력에 대한 것을
   한꺼번에 만드는데.. 지금은 쪼개는 방법을 익숙하게 하기 위해서
   쪼개서 사용한다!

- CRUD 메서드 명(대표적인)
     insert < 삽입
     select, get 
     update
     delete < 삭제

-----ProductDAO

package model;
import java.util.ArrayList;
// CRUD
public class ProductDAO {
	// DB를 대체하는 컬렉션(배열리스트)
	ArrayList<ProductVO> datas;
	private int pk = 101; // 후위증감 연산을 선호한다
	// 어딘가에서 DAO 사용할텐데, 
	// DAO가 생성되면 그 즉시 datas도 생성되게끔 하고 싶다!
	// == DAO의 멤버변수인 datas도 값을 가질 수 있게 만들고 싶어요~
	// 생성자를 써야한다.
	public ProductDAO() { // default로 만들면 다른 패키지에서 쓸 수 없다...
		// 앞으로 public을 붙여서 사용!
		datas= new ArrayList<ProductVO>();
		// 초기데이터(혹은 샘플 데이터)
		datas.add(new ProductVO(pk++, "콜라", 1200));
		datas.add(new ProductVO(pk++, "사이다", 900, 5));
		datas.add(new ProductVO(pk++, "환타", 800, 2));
	}
	// 관리자
	// 새로운 음료 추가
	// 음료 재고 추가
	// 음료 삭제
	// 사용자(서비스)
	// 음료 출력
	// 음료 구매
	public ArrayList<ProductVO> selectAll() { // getAll()
		//DB에서는 선택하는 행위를 SelectAll()로 쓰이는 경우가 많다.
		// 여기서 출력을 한다?? 잘못된거다!
		// 직접 로직을 구현하는 경우가 있는데 그거 잘못된것이다!!
		// View측에서 무엇을 필요로 할 지 고려!
		System.out.println("로그 : selectAll()");
		return datas;
	}
	public ProductVO selectOne(int num) { // getOne() R에 해당
		for(int i = 0; i < datas.size(); i++) {
			if(num==datas.get(i).getNum()) {
				System.out.println("로그 : " + datas.get(i) + " 반환");
				return datas.get(i);
			}
		}
		System.out.println("로그 : 반환xxx -> 확인 필요!");
		return null; // 만날 확률이 거의 없다.
		// 이상한 숫자가 들어오게 되면 null값을 되돌려준다.
		// 이상한 숫자가 들어올 일이 없기 때문이다.
		// 유효성검사를 View가 해줄 것이다.
	}
	// 음료 구매
	// 사용자가 pk 입력
	// pk에 해당하는 음료를 출력
	// 구매 시도 시 음료의 재고 -- 
	public boolean update(ProductVO vo) { // U에 해당
		// 실무에서는 다르게 작성하기도 하다(void도 하지만 boolean값도 쓰인다
		// update의 성공 여부
		if(vo.getCnt()==0) {
			System.out.println("로그 : " + vo.getNum() + " 재고가 없습니다.");
			return false;
		}
		vo.setCnt(vo.getCnt()-1); 
		System.out.println("로그 : " + vo.getNum() + " 구매 완료!");
		return true;
	}
	// 음료추가
	public boolean insert(String name, int price) {
		// boolean값으로 하는 것이 일반적이다 => 성공하면 true, 실패하면 false
		// 현재 프로그램 생성자가 오버로딩되어있어서
		// 재고가 없어도 메뉴생성이 가능함
		// -> 메서드 오버로딩
		return false;
	}
	public boolean insert(String name, int price, int cnt) {
		try {
			// productVO에 새 값 추가
			ProductVO vo = new ProductVO(pk++, name, price, cnt);
			datas.add(vo);
			System.out.println("   로그 : 메뉴추가성공!");
			return true;
		}
		catch(Exception e){ // 예외발생 시 로그 남겨주기
			System.out.println("    로그 : 메뉴추가실패 : 확인이 필요한 예외발생!");
			e.printStackTrace(); // 어떤 예외인지 출력!
			return false;
		}
	}
	// 재고 추가
	public boolean update(int num, int cnt) { // 상품 넘버, 재고량!
		// input 2개, output 1개(boolean)
		// 위의 update의 오버로딩
		for(int i = 0; i < datas.size(); i++) { // 처음부터 끝까지 돈다
			if(datas.get(i).getNum()==num) { // 만약 넘버가 같으면?
				datas.get(i).setCnt(datas.get(i).getCnt()+cnt); // 재고량 늘린다!
				return true; // 성공하면 true반환
			}
		}
		return false; // 실패
	}
	public boolean delete(int num) {
		for(int i = 0; i < datas.size(); i++) { // 처음부터 끝까지 돈다
			if(datas.get(i).getNum()==num) { // 만약 넘버가 같으면?
				datas.remove(i); // 제거한다!
				return true; // 성공하면 true반환
			}
		}
		return false; // 실패
	}
}
// 이걸로 model의 역할을 끝!

 

-----ProductView---

package view;
import java.util.ArrayList;
import java.util.Scanner;
import javax.sql.DataSource;
import javax.xml.crypto.Data;
import model.ProductVO;
public class ProductView {
	Scanner sc = new Scanner(System.in);
	public int action;
	public void startView() {
		while(true) { // 유효성 검사 -> 꼼꼼하게 작업해보기!
			System.out.println("=== 자판기 ===");
			System.out.println("1.메뉴확인 2.구매 3.종료");
			System.out.print("입력) ");
			action = sc.nextInt();
			if(action >= 1 && action <=3 || action == 1234) { // 관리자모드 1234
				break;
			}
			System.out.println("범위외입력!");
		}
	}
	/*
	public void manageView() {
		while(true) {
			System.out.println("=== 관리자모드 ===");
			System.out.println("1.음료추가 2.음료재고추가 3.음료삭제 4.종료");
			System.out.print("입력) ");
			action = sc.nextInt();
			if(action >= 1 && action <= 4) {
				break;
			}
			System.out.println("범위외입력!");
		}
	}
	public void funcM1(ArrayList<ProductVO> datas) {
		System.out.print("추가할 음료와 가격을 입력하세요) ");
		String name = sc.next();
		int price = sc.nextInt();
	}
	*/
	public void func1(ArrayList<ProductVO> datas) {
		for(int i = 0; i < datas.size(); i++) {
			System.out.println((i+1)+"번 메뉴 " + datas.get(i).getName());
		}
	}
	public void func2(ArrayList<ProductVO> datas) {
		for(int i = 0; i < datas.size(); i++) {
			System.out.print(datas.get(i).getNum()+"번 메뉴");
			if(datas.get(i).getCnt()==0) {
				System.out.println("x");
				continue;
			}
			System.out.println(datas.get(i).getName());
		}
		while(true) {
			System.out.print("메뉴 입력 ) ");
			action = sc.nextInt();
			if(1<=action && action <= datas.size()) {
				break;
			}
			System.out.println("상품번호 확인 후 다시 입력해주세요!");
		}
		// action += 100; -> Controller 에서 해야한다고 강사님은 생각!
		// 상품번호가 몇번인지 모르는게 맞기 때문에!
	}
	public void funcT(ProductVO vo) {
		System.out.println(vo.getName() + "구매완료!");
	}
	public void funcF(ProductVO vo) {
		System.out.println(vo.getName() + " 재고가 없습니다...");
	}
	public void func3() {
		System.out.println("프로그램이 종료됩니다");
		for(int i = 0; i < 5; i++) {
			System.out.println(".");
			try {
				Thread.sleep(1000); // 1000당 1초 재운다 == sleep
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
		}
		System.out.println();
	}
	// 1~3 메뉴를 보여주는 출력문구(겹친건 지운다)
	// 음료추가
	// 음료이름입력
	// 음료가격입력
	// 음료재고입력
	// 음료 삭제
	// 수행이 완료되었습니다!(삭제 + 추가)
	// 수행실패! 다음에 다시 이용해주세요..
	// 음료재고추가
	// 번호입력
	// 음료삭제
	// 번호입력<- 위에 있으니 필요없다
	public void admin_func1() { // 관리자모드
		// return할 필요없이 이렇게 진행해도 된다!
		while(true) { // 무한반복(if문 확인되면 break)
			System.out.println("=== 관리자 모드 ===");
			System.out.println("1.음료추가 2.재고추가 3.음료삭제 4.관리자모드 종료");
			System.out.print("입력) ");
			action = sc.nextInt();
			if(1<=action&&action<=4) {
				break;
			}
			System.out.println("범위외입력!");
		}
	}
	public void admin_func2() { // 음료 추가
		System.out.println("음료추가 메뉴입니다.");
	}
	// 음료를 만드는 메서드로 묶어버리면
	// 재고를 추가하는 기능을 한번 더 만들어야한다.
	// 한 줄만 뜰 수 있게 만들게 다 따로 만드는 것이 좋다!!
	public String admin_func3() { // 음료이름입력
		System.out.print("음료 이름을 입력) ");
		String name = sc.next();
		return name;
	}
	public int admin_func4() { // 음료가격입력
		System.out.print("음료 가격을 입력) ");
		int price = sc.nextInt();
		return price;
	}
	public int admin_func5() { // 음료재고입력
		System.out.print("음료 재고를 입력) ");
		int cnt = sc.nextInt();
		return cnt;
	}
	public void admin_func6() { // 수행이 완료되었습니다!
		System.out.println("수행이 완료되었습니다!");
	}
	public void admin_func7() { // 수행실패! 다음에 다시 이용해주세요...
		System.out.println("수행실패! 다음에 다시 이용해주세요...");
	}
	public void admin_func8() { // 음료재고추가
		System.out.println("음료재고추가 메뉴입니다.");
	}
	public int admin_func9() { // 번호입력
		System.out.print("번호 입력) ");
		int num = sc.nextInt();
		return num;
	}
	public void admin_func10() { // 음료 삭제
		System.out.println("음료삭제 메뉴입니다.");
	}
}

 

 

-----ProductController

package controller;
import model.ProductDAO;
import model.ProductVO;
import view.ProductView;
public class ProductController {
	ProductDAO model;
	ProductView view;
	public ProductController() {
		model = new ProductDAO();
		view = new ProductView();
	}
	public void startApp() {
		while(true) {
			view.startView();
			if(view.action==1) {
				view.func1(model.selectAll());
			}
			else if(view.action==2) {
				view.func2(model.selectAll());
				// 사용자가 먹고 싶은 메뉴의 번호를 입력햇는데,
				// C에서 [view.action]
				// C 에서는 사용자가 입력한 메뉴의 번호를 view.action으로 참조 가능하고,
				// M은 pk를 입력받으면 상품객체를 줄 준비가 되어있습니다.
				int num =view.action;// V에서 사용자가 입력한 메뉴 번호 pk 해당
				ProductVO vo = model.selectOne(num+ 100);
				// pk를 넣으면 해당하는 상품을 반환하는 M의 selectOne()메서드
				boolean flag = model.update(vo);
				// M은 반환받은(==사용자가 선택한) 객체의 재고를 --
				// boolean flag=model.update(model.selectOne(view.action+100)); // 상품객체 전달
				if(flag) {
					view.funcT(vo);
				}
				else {
					view.funcF(vo);
				}
			}
			else if(view.action==3) {
				view.func3();
				break;
			}
			else if(view.action == 1234) { // 관리자모드
				view.admin_func1();
				while(true) {
					if(view.action==1) { // 메뉴 추가
						view.admin_func2();
						String name = view.admin_func3();
						int price = view.admin_func4();
						int cnt = view.admin_func5();
						if(model.insert(name, price, cnt)) { // 잘 들어가게 되면!
							view.admin_func6(); // 성공 출력
						}
						else {
							view.admin_func7(); // 실패 출력
						}
					}
					else if(view.action==2) { // 메뉴 재고 업데이트
						view.admin_func8();
						view.func1(model.selectAll()); // 메뉴 전부 호출
						int num = view.admin_func9(); // 메뉴번호
						int cnt = view.admin_func5(); // 메뉴 재고
						if(model.update(num, cnt)) { // 만약 업데이트가 되면?
							view.admin_func6(); // 출력
						}
						else {
							view.admin_func7();
						}
					}
					else if(view.action==3) { // 메뉴 제거
						view.admin_func10();
						int num = view.admin_func9();
						if(model.delete(num)) {
							view.admin_func6();
						}
						else {
							view.admin_func7();
						}
					}
					else if(view.action==4) {
						view.func3(); // 숫자넣지 말고 영어로 기능을 유추할 수 있게
						break;
					}
				}
			}
		}
	}
}