Christmas Pikachu MVC 패턴 활용한 미니 쇼핑몰 프로그램
개발일지/복습

MVC 패턴 활용한 미니 쇼핑몰 프로그램

ZI_CO 2023. 12. 18.

Client 클래스

package client;

import ctrl.CTRL;

public class Client {
	public static void main(String[] args) {
		CTRL app=new CTRL();
		app.start();
	}
}

 

 

Controller 클래스

package ctrl;

import java.util.ArrayList;

import model.MemberDAO;
import model.MemberDTO;
import model.ProductDAO;
import model.ProductDTO;
import view.AdminVIEW;
import view.CommonVIEW;
import view.LoginVIEW;
import view.LogoutVIEW;
import view.UserVIEW;

public class CTRL {
	private MemberDAO mDAO;
	private ProductDAO pDAO;
	private AdminVIEW adminVIEW;
	private UserVIEW userVIEW;
	private CommonVIEW commonVIEW;
	private LoginVIEW loginVIEW;
	private LogoutVIEW logoutVIEW;

	private MemberDTO loginINFO; // 로그인한 사용자의 데이터를 저장할 공간
	private ArrayList<ProductDTO> cart; // 장바구니 데이터를 저장할 공간
	public CTRL() {
		mDAO=new MemberDAO();
		pDAO=new ProductDAO();
		adminVIEW=new AdminVIEW();
		userVIEW=new UserVIEW();
		commonVIEW=new CommonVIEW();
		loginVIEW=new LoginVIEW();
		logoutVIEW=new LogoutVIEW();

		loginINFO=null;
		cart=null;
	}

	// 모듈화
	public void loginAction() {
		String mid=logoutVIEW.inputMid();
		String mpw=logoutVIEW.inputMpw();

		MemberDTO mDTO=new MemberDTO();
		mDTO.setMid(mid);
		mDTO.setMpw(mpw);
		mDTO.setSearchCondition("로그인");
		loginINFO=mDAO.selectOne(mDTO);

		if(loginINFO==null) {
			commonVIEW.printFalse();
			return;
		}
		commonVIEW.printTrue();
	}

	public void start() {
		while(true) {
			commonVIEW.printMenu();
			if(loginINFO==null) {
				logoutVIEW.printMenu();
			}
			else if(loginINFO.getGrade().equals("ADMIN")) {
				adminVIEW.printMenu();
				loginVIEW.hello(loginINFO);
			}
			else {
				if(cart!=null) {
					userVIEW.printMenu(cart.size());
				}
				else{
					userVIEW.printMenu(0);
				}
				loginVIEW.printMenu();
				loginVIEW.hello(loginINFO);
			}
			int action=commonVIEW.inputAction();

			// ※ 모든 action 수행은 자격이 있다고 가정하고 하겠습니다.
			// ※ 즉, 별도의 인증 작업을 생략하겠습니다.

			if(action==0) {
				break;
			}
			else if(action==1) {
				// MODEL아, 전체목록주라! == SELECTALL
				// 받은것들 뷰에서 출력

				commonVIEW.printDatas(pDAO.selectAll(new ProductDTO()));
			}
			else if(action==2) {

				// ※ 최저 → 최고 가격 순서로 입력을 잘 했다고 가정하고 하겠습니다.

				// 최저가격입력
				// 최고가격입력
				// MODEL아, 가격검색목록주라! == SEELCTALL
				// 받은것들 뷰에서 출력		

				/*
				int 최저가격=commonVIEW.inputPrice();
				int 최고가격=commonVIEW.inputPrice();
				commonVIEW.printDatas(pDAO.selectAll(new ProductDTO()));

				int 최저가격=commonVIEW.inputPrice();
				int 최고가격=commonVIEW.inputPrice();
				ProductDTO pDTO=new ProductDTO();
				pDTO.setPrice(최저가격);
				pDTO.setPrice(최고가격);
				commonVIEW.printDatas(pDAO.selectAll(pDTO));
				 */

				int minPrice=commonVIEW.inputPrice();
				int maxPrice=commonVIEW.inputPrice();
				ProductDTO pDTO=new ProductDTO();
				pDTO.setMinPrice(minPrice); // searchCondition의 역할
				pDTO.setMaxPrice(maxPrice); // JAVA 로직에서만 활용되는 DTO의 멤버변수
				pDTO.setSearchCondition("가격검색");
				commonVIEW.printDatas(pDAO.selectAll(pDTO));
			}
			else if(action==3) {
				if(loginINFO==null) {
					commonVIEW.printInfo();

					loginAction();

					continue;
				}				

				int pid=commonVIEW.inputPid();
				ProductDTO pDTO=new ProductDTO();
				pDTO.setPid(pid);
				pDTO=pDAO.selectOne(pDTO);
				if(pDTO==null) {
					commonVIEW.printNoData();
					continue;
				}

				commonVIEW.printData(pDTO);
				int cnt=commonVIEW.inputCnt();

				boolean flag=false;
				int i=0;
				if(cart!=null) {					
					for(i=0;i<cart.size();i++) {
						if(pDTO.getPid()==cart.get(i).getPid()) {
							flag=true;
							break;
						}
					}
				}

				// 원래는 그냥 지금 구매하려는 재고가 기존 재고보다 크면 안된다.
				// 현재는 지금 구매하려는 재고가 기존 재고-장바구니 재고보다 크면 안된다.				
				if(!flag) {
					if(pDTO.getCnt() < cnt) {
						commonVIEW.printFalse();
						continue;
					}
					if(cart==null) {
						cart=new ArrayList<ProductDTO>();
					}
					ProductDTO data=new ProductDTO();
					data.setPid(pDTO.getPid());
					data.setName(pDTO.getName());
					data.setCnt(cnt);
					data.setPrice(pDTO.getPrice());
					cart.add(data);
					commonVIEW.printTrue();
				}
				else { // 장바구니에 있던 상품이라면
					if(pDTO.getCnt()-cart.get(i).getCnt() < cnt) {
						commonVIEW.printFalse();
						continue;
					}
					cart.get(i).setCnt(cart.get(i).getCnt()+cnt);
					commonVIEW.printTrue();
				}
			}
			else if(action==4) {
				userVIEW.printTotalPrice(cart);
				for(int i=0;i<cart.size();i++) {
					cart.get(i).setSearchCondition("구매");
					if(!pDAO.update(cart.get(i))) {
						commonVIEW.printFalse();
						continue;
					}
					commonVIEW.printTrue();
				}
				cart=null; // cart.clear();
			}
			else if(action==5) {
				// 재고추가
			}
			else if(action==6) {
				String mid;
				while(true) {
					mid=logoutVIEW.inputMid();
					MemberDTO mDTO=new MemberDTO();
					mDTO.setMid(mid);
					mDTO.setSearchCondition("ID중복검사");
					if(mDAO.selectOne(mDTO)==null) { // 중복이 아니라면
						break;
					}
					logoutVIEW.printInfo();
				}
				String mpw=logoutVIEW.inputMpw();
				String name=logoutVIEW.inputName();

				MemberDTO mDTO=new MemberDTO();
				mDTO.setMid(mid);
				mDTO.setMpw(mpw);
				mDTO.setName(name);
				mDTO.setGrade("USER");
				if(!mDAO.insert(mDTO)) {
					commonVIEW.printFalse();
					continue;
				}
				commonVIEW.printTrue();
			}
			else if(action==7) {
				loginAction();
			}
			else if(action==8) {
				loginINFO=null;
				cart=null; // cart.clear();
				commonVIEW.printTrue();
			}
			else if(action==9) {
				// 비밀번호를 확인한후에 비번변경을 진행
				String mpw=logoutVIEW.inputMpw();
				MemberDTO mDTO=new MemberDTO();
				mDTO.setMid(loginINFO.getMid());
				mDTO.setMpw(mpw);
				mDTO.setSearchCondition("로그인");
				mDTO=mDAO.selectOne(mDTO);
				if(mDTO==null) {
					commonVIEW.printFalse();
					continue;
				}

				// 변경할 비번입력
				mpw=logoutVIEW.inputMpw();
				mDTO.setMid(loginINFO.getMid());
				mDTO.setMpw(mpw);
				if(!mDAO.update(mDTO)) {
					commonVIEW.printFalse();
					continue;
				}
				loginINFO=null;
				cart=null;
				commonVIEW.printTrue();
			}
			else if(action==10) {
				if(!mDAO.delete(loginINFO)) {
					commonVIEW.printFalse();
					continue;
				}
				loginINFO=null;
				cart=null;
				commonVIEW.printTrue();
			}
		}
	}
}

 

 

 

 

MemberDTO 클래스

package model;

public class MemberDTO {
	private String mid; // PK
	private String mpw;
	private String name;
	private String grade;
	
	private String searchCondition;
	
	public String getSearchCondition() {
		return searchCondition;
	}
	public void setSearchCondition(String searchCondition) {
		this.searchCondition = searchCondition;
	}
	
	public String getMid() {
		return mid;
	}
	public void setMid(String mid) {
		this.mid = mid;
	}
	public String getMpw() {
		return mpw;
	}
	public void setMpw(String mpw) {
		this.mpw = mpw;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getGrade() {
		return grade;
	}
	public void setGrade(String grade) {
		this.grade = grade;
	}
	@Override
	public String toString() {
		return "MemberDTO [mid=" + mid + ", mpw=" + mpw + ", name=" + name + ", grade=" + grade + "]";
	}
}

 

 

 

 

MemberDAO 클래스

package model;

import java.util.ArrayList;

public class MemberDAO {
	private ArrayList<MemberDTO> mdatas;
	public MemberDAO() {
		mdatas=new ArrayList<MemberDTO>();

		MemberDTO sample01=new MemberDTO();
		sample01.setMid("admin");
		sample01.setMpw("1234");
		sample01.setName("관리자");
		sample01.setGrade("ADMIN");
		mdatas.add(sample01);

		MemberDTO sample02=new MemberDTO();
		sample02.setMid("teemo");
		sample02.setMpw("1234");
		sample02.setName("작은티모");
		sample02.setGrade("USER");
		mdatas.add(sample02);
	}

	// ※ 사용하지않는 DAO의 CRUD(비즈니스 메서드,핵심 관심,핵심 로직)는
	//    private으로 은닉했습니다.

	private ArrayList<MemberDTO> selectAll(MemberDTO mDTO) {
		return null;
	}
	public MemberDTO selectOne(MemberDTO mDTO) {
		if(mDTO.getSearchCondition().equals("로그인")) {
			boolean flag=false;
			int i;
			for(i=0;i<mdatas.size();i++) {
				if(mdatas.get(i).getMid().equals(mDTO.getMid())) {
					System.out.println("[로그] ID 일치");
					if(mdatas.get(i).getMpw().equals(mDTO.getMpw())) {
						System.out.println("[로그] PW 일치");
						flag=true;
						break;
					}
				}
			}
			if(!flag) {
				return null;
			}
			return mdatas.get(i);
		}
		else { // ID중복검사
			boolean flag=false;
			int i;
			for(i=0;i<mdatas.size();i++) {
				if(mdatas.get(i).getMid().equals(mDTO.getMid())) {
					System.out.println("[로그] ID 일치");
					flag=true;
					break;
				}
			}
			if(!flag) {
				return null;
			}
			return mdatas.get(i);
		}
	}
	public boolean insert(MemberDTO mDTO) {
		try {
			MemberDTO data=new MemberDTO();
			data.setMid(mDTO.getMid());
			data.setMpw(mDTO.getMpw());
			data.setName(mDTO.getName());
			data.setGrade(mDTO.getGrade());
			mdatas.add(data);
		}catch(Exception e) {
			System.out.println("[로그] memberDAO.insert()에서 예외발생!");
			return false;
		}
		return true;
	}
	public boolean update(MemberDTO mDTO) {
		boolean flag=false;
		int i;
		for(i=0;i<mdatas.size();i++) {
			if(mdatas.get(i).getMid().equals(mDTO.getMid())) {
				flag=true;
				break;
			}
		}
		if(!flag) {
			return false;
		}
		mdatas.get(i).setMpw(mDTO.getMpw());
		return true;
	}
	public boolean delete(MemberDTO mDTO) {
		boolean flag=false;
		int i;
		for(i=0;i<mdatas.size();i++) {
			if(mdatas.get(i).getMid().equals(mDTO.getMid())) {
				flag=true;
				break;
			}
		}
		if(!flag) {
			return false;
		}
		mdatas.remove(i);
		return true;
	}
}

 

 

 

 

 

ProductDTO 클래스

package model;

public class ProductDTO {
	private int pid;
	private String name;
	private int price;
	private int cnt;

	private int minPrice; // JAVA 로직에서만 사용할 멤버변수
	private int maxPrice;
	private String searchCondition;
	private int addCnt;

	public int getAddCnt() {
		return addCnt;
	}
	public void setAddCnt(int addCnt) {
		this.addCnt = addCnt;
	}
	public String getSearchCondition() {
		return searchCondition;
	}
	public void setSearchCondition(String searchCondition) {
		this.searchCondition = searchCondition;
	}
	public int getMinPrice() {
		return minPrice;
	}
	public void setMinPrice(int minPrice) {
		this.minPrice = minPrice;
	}
	public int getMaxPrice() {
		return maxPrice;
	}
	public void setMaxPrice(int maxPrice) {
		this.maxPrice = maxPrice;
	}

	public int getPid() {
		return pid;
	}
	public void setPid(int pid) {
		this.pid = pid;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public int getCnt() {
		return cnt;
	}
	public void setCnt(int cnt) {
		this.cnt = cnt;
	}
	@Override
	public String toString() {
		return "ProductDTO [pid=" + pid + ", name=" + name + ", price=" + price + ", cnt=" + cnt + "]";
	}
}

 

 

 

 

ProductDAO 클래스

package model;

import java.util.ArrayList;

public class ProductDAO {
	private ArrayList<ProductDTO> pdatas;
	public ProductDAO() {
		pdatas=new ArrayList<ProductDTO>();

		ProductDTO sample01=new ProductDTO();
		sample01.setPid(1001);
		sample01.setName("콜라");
		sample01.setPrice(1100);
		sample01.setCnt(10);
		pdatas.add(sample01);

		ProductDTO sample02=new ProductDTO();
		sample02.setPid(1002);
		sample02.setName("사이다");
		sample02.setPrice(1200);
		sample02.setCnt(1);
		pdatas.add(sample02);

		ProductDTO sample03=new ProductDTO();
		sample03.setPid(1003);
		sample03.setName("보리차");
		sample03.setPrice(2200);
		sample03.setCnt(0);
		pdatas.add(sample03);
	}
	public ArrayList<ProductDTO> selectAll(ProductDTO pDTO) {
		if(pDTO.getSearchCondition()==null) { // 상품전체목록
			return pdatas;			
		}
		else { // 가격검색
			ArrayList<ProductDTO> datas=new ArrayList<ProductDTO>();
			for(int i=0;i<pdatas.size();i++) {
				if(pDTO.getMinPrice()<=pdatas.get(i).getPrice() && pdatas.get(i).getPrice()<=pDTO.getMaxPrice()) {
					ProductDTO data=new ProductDTO();
					data.setPid(pdatas.get(i).getPid());
					data.setName(pdatas.get(i).getName());
					data.setPrice(pdatas.get(i).getPrice());
					data.setCnt(pdatas.get(i).getCnt());
					datas.add(data);
				}
			}
			return datas;
		}
	}
	public ProductDTO selectOne(ProductDTO pDTO) {
		boolean flag=false;
		int i;
		for(i=0;i<pdatas.size();i++) {
			if(pDTO.getPid()==pdatas.get(i).getPid()) {
				flag=true;
				break;
			}
		}
		if(!flag) {
			return null;
		}
		return pdatas.get(i);
	}
	private boolean insert(ProductDTO pDTO) {
		return false;
	}
	public boolean update(ProductDTO pDTO) {
		if(pDTO.getSearchCondition().equals("구매")) {
			boolean flag=false;
			int i;
			for(i=0;i<pdatas.size();i++) {
				if(pDTO.getPid()==pdatas.get(i).getPid()) {
					flag=true;
					break;
				}
			}
			if(!flag) {
				return false;
			}
			/// pdatas.get(i).setCnt(pdatas.get(i).getCnt()-1); // 1개 구매
			pdatas.get(i).setCnt(pdatas.get(i).getCnt()-pDTO.getCnt()); // N개 구매
			return true;
		}
		else { // 재고추가
			boolean flag=false;
			int i;
			for(i=0;i<pdatas.size();i++) {
				if(pDTO.getPid()==pdatas.get(i).getPid()) {	
					flag=true;
					break;
				}
			}
			if(!flag) {
				return false;
			}
			pdatas.get(i).setCnt(pdatas.get(i).getCnt()+pDTO.getAddCnt());
			return true;
		}
	}
	private boolean delete(ProductDTO pDTO) {
		return false;
	}
}

 

 

 

 

AdminView 클래스

package view;

public class AdminVIEW extends VIEW {

	public void printMenu() {
		System.out.println("5. 재고추가");
	}

}

 

 

 

 

 

CommonView 클래스

package view;

import java.util.ArrayList;

import model.ProductDTO;

public class CommonVIEW extends VIEW {
	
	public void printMenu() {
		System.out.println("0. 프로그램종료");
		System.out.println("1. 상품목록전체출력");
		System.out.println("3. 상품선택");
	}
	
	public void printInfo() {
		System.out.println("해당 메뉴는 로그인후에 이용하실수있습니다! :D");
	}
	
	public int inputPid() {
		int pid;
		while(true) {
			System.out.print("상품번호입력 >> ");
			pid=sc.nextInt();
			if(1001<=pid && pid<=2000) {
				break;
			}
			System.out.println("제대로 입력해주세요!");
		}
		return pid;
	}
	public void printNoData() {
		System.out.println("해당 정보는 없습니다...");
	}
	public int inputCnt() {
		int cnt;
		while(true) {
			System.out.print("재고입력 >> ");
			cnt=sc.nextInt();
			if(1<=cnt && cnt<=100) {
				break;
			}
			System.out.println("제대로 입력해주세요!");
		}
		return cnt;
	}
	public void printTrue() {
		System.out.println("성공!");
	}
	public void printFalse() {
		System.out.println("실패...");
	}
	public int inputAction() {
		int action;
		while(true) {
			System.out.print("번호입력 >> ");
			action=sc.nextInt();
			if(0<=action && action<=10) {
				break;
			}
			System.out.println("제대로 입력해주세요!");
		}
		return action;
	}
	public int inputPrice() {
		int price;
		while(true) {
			System.out.print("가격입력 >> ");
			price=sc.nextInt();
			if(1<=price && price<=1000000) {
				break;
			}
			System.out.println("제대로 입력해주세요!");
		}
		return price;
	}
	public void printDatas(ArrayList<ProductDTO> datas) {
		// DTO는 자료형에 불과합니다.
		// M, V, C 어디에서나 사용가능합니다!
		if(datas==null || datas.size()<=0) {
			System.out.println("출력할 데이터가 없습니다!");
		}
		for(ProductDTO data:datas) {
			if(data.getCnt()<=0) {
				System.out.println(data.getName()+"는 재고가 없습니다.");
				continue;
			}
			System.out.println(data);
		}
	}
	public void printData(ProductDTO data) {
		if(data==null || data.getPid()==0) {
			System.out.println("출력할 데이터가 없습니다!");
		}
		System.out.println(data);
	}
	
}

 

 

 

 

 

LoginView 클래스

package view;

import model.MemberDTO;

public class LoginVIEW extends VIEW {
	
	public void printMenu() {
		System.out.println("8. 로그아웃");
		System.out.println("9. 비밀번호변경");
		System.out.println("10. 회원탈퇴");
	}
	
	public void hello(MemberDTO data) {
		System.out.println(data.getName()+"님, 안녕하세요! :D");
	}
	
}

 

 

 

 

LogoutView 클래스

package view;

public class LogoutVIEW extends VIEW {
	
	public void printMenu() {
		System.out.println("6. 회원가입");
		System.out.println("7. 로그인");
	}
	
	public void printInfo() {
		System.out.println("중복되는 ID입니다! 다시 입력해주세요!");
	}
	public String inputMid() {
		System.out.print("ID 입력 >> ");
		String mid=sc.next();
		return mid;
	}
	public String inputMpw() {
		System.out.print("PW 입력 >> ");
		String mpw=sc.next();
		return mpw;
	}
	public String inputName() {
		System.out.print("이름 입력 >> ");
		String name=sc.next();
		return name;
	}
	public String inputGrade() {
		String result="USER";
		
		System.out.println("1. 사용자");
		System.out.println("2. 관리자");
		System.out.print("번호 입력 >> ");
		int action=sc.nextInt();
		
		if(action==2) {
			System.out.println("관리자 회원가입을 위한 비밀번호를 입력해주세요.");
			System.out.print("입력 >> ");
			int num=sc.nextInt();
			if(1234==num) { // '하드코딩'되어있는 비밀번호
				result="ADMIN";
			}
		}
		
		return result;
	}
	
}

 

 

 

 

 

UserView 클래스

package view;

import java.util.ArrayList;

import model.ProductDTO;

public class UserVIEW extends VIEW {

	public void printMenu(int cnt) {
		System.out.println("2. 가격검색출력");
		if(cnt>0) {
			System.out.println("4. 장바구니에 저장된 상품 구매");
		}
	}

	public void printTotalPrice(ArrayList<ProductDTO> cart) {
		int total=0;
		for(ProductDTO data:cart) {
			total+=data.getPrice()*data.getCnt();
		}
		System.out.println("총 구매 금액은 "+total+"원입니다.");
	}

}

 

 

 

 

 

View 클래스

package view;

import java.util.Scanner;

// VIEW 추상클래스는 객체를 생성하려는 목표 xxx
// VIEW류의 클래스들을 정의하려는 목표 O
// § 메서드를 강제로 정의(오버라이딩 강제)하고싶다면, "인터페이스"
// § sc라는 '멤버변수'를 가져야한다는것을 정의하고싶었기에 "추상클래스"
public abstract class VIEW {
	protected Scanner sc; // 나와 내 자식까지 사용가능한 접근제어자 범위
	public VIEW() {
		sc=new Scanner(System.in);
	}
}

댓글