본문 바로가기

언어/Java

Product 예제 3

※ 컬렉션 프레임워크 자료구조형으로 바꾸기

package com.my.product.dto;

import java.util.Objects;

public class Product {
	private String prodNo;
	private String prodName;
	private int prodPrice;
	
	public Product() {
	}
	
	public Product(String prodNo, String prodName) {
		this(prodNo, prodName, 0);
	}
	
	public Product(String prodNo, String prodName, int prodPrice) {
		if(prodNo.length() != 5) {
			System.out.println("상품번호는 5자리어야합니다");
		} else {
			this.prodNo = prodNo;
			this.prodName = prodName;
			this.prodPrice = prodPrice;
		}
	}

    public void setProdNo(String prodNo) {
		if(prodNo.length() != 5) {
			System.out.println("상품번호는 5자리어야합니다");
			return;
		}
		this.prodNo = prodNo;
	}
	
	public String getProdNo() {
//		return "prodNo의 암호화";
		return prodNo;
	}
	
	public void setProdName(String prodName) {
		this.prodName = prodName;
	}
	
	public String getProdName() {
		return prodName;
	}
	
	public void setProdPrice(int prodPrice) {
		this.prodPrice = prodPrice;
	}
	
	public int getProdPrice() {
		return prodPrice;
	}
	
//	public boolean equals(Object obj) {} 이건 상속이고 아래는 오버로드한 것.
  	public boolean equals(Product p) {
  		return this.prodNo.equals(p.prodNo);
  	}

//	public boolean equals(String no) {
//		return this.prodNo.equals(no);
//	}
	
	@Override
	public int hashCode() {
		return Objects.hash(prodNo);
	}

	/* 이클립스가 만들어준거에 섞은거
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
//		if (getClass() != obj.getClass())
//			return false;
		// 인자로 product type아니면 죄다 retur false
		Class currentClass = this.getClass();
		Class paramClass = obj.getClass();
		if(currentClass != paramClass) {
			return false;
		}
		
		Product other = (Product) obj;
		return Objects.equals(prodNo, other.prodNo);
	}	자동생성됨 */ 
	
	// this.getProdNo() = this.prodNo;
    // p.getProdNo()
	//여기있는 빔프로젝터, 1강의장의 빔프로젝터
	
	@Override	//위에꺼 말고 이렇게도 가능
	public boolean equals(Object obj) {
		if(obj == null) {
			return false;
		}
		if(obj instanceof Product) {
			Product product = (Product)obj;
			if(this.prodNo.equals(product.prodNo)) {
				return true;
			}
		}
		return false;
	}	
}
package com.my.product.dao;

import com.my.exception.AddException;
import com.my.exception.FindException;
import com.my.exception.ModifyException;
import com.my.exception.RemoveException;
import com.my.product.dto.Product;

public interface ProductDAOInterface {	// 모든 메서드는 추상메서드
	/**
	 * 상품을 저장소에 저장한다. 저장소가 꽉찬 경우 "저장소가 꽉찼습니다" 메시지가 출력되고 저장안된다.
	 * @param product 상품
	 */	
	void insert(Product product) throws AddException ;	// abstract가 생략된 형태 = public abstract void insert(Product product);와 같음
	// 부모 자식 동일해야해서  throws AddException 넣어줌 부모쪽에 선언한 Exception만 자식쪽에서 선언가능
	
	/**
	 * 상품번호에 해당 상품을 저장소에서 검색하여 반환한다
	 * @param prodNo 상품번호
	 * @return 상품객체.
	 * @throws FindException; 번호에 해당 상품을 찾지 못하면 예외발생한다.
	 */
	Product selectByProdNo(String no) throws FindException;	// 사용자정의 Exception java.lang 있지만 만들것
	
	/**
	 * 저장소에 저장된 상품들만 반환한다
	 * @return 상품들.
	 * @throws FindException; 저장소에 저장된 상품이 한개도 없으면 예외발생한다.
	 */
//	Product[] selectAll() throws FindException;
	Object selectAll() throws FindException;

	/**
	 * 변경할 상품의 상품번호와 같은 상품을 저장소에서 찾아낸다
	 * 변경할 상품의 상품명 또는 가격으로 저장소 상품정보를 변경한다
	 * @param p 변경할 상품. 상품번호는 반드시 필요, 
	 * 					  p의 가격이 0이면 저장소 상품의 가격 변경안함,
	 * 					  p의 이름이 null이면 저장소 상품의 이름 변경안함
	 * @throws ModifyException; 변경할 상품이 없으면 예외발생한다
	 */
	void update(Product p) throws ModifyException;
	/**
	 * 상품을 삭제한다
	 * @param prodNo 상품번호
	 * @throws RemoveException; 삭제할 상품이 없으면 예외발생한다
	 */
	void delete(String prodNo) throws RemoveException;
}
package com.my.product.dao;

import java.util.ArrayList;
import java.util.List;

import com.my.exception.AddException;
import com.my.exception.FindException;
import com.my.exception.ModifyException;
import com.my.exception.RemoveException;
import com.my.product.dto.Product;

public class ProductDAOList implements ProductDAOInterface {
	private List<Product> products;
	public ProductDAOList() {
		products = new ArrayList<>();
	}
	
	@Override
	public void insert(Product product) throws AddException {
		for(Product p : products) {
//			if(p.getProdNo().equals(product.getProdNo())) {
			if(p.equals(product)) {	//object의 equals 말고  Product에서 따로 만들어서 써보기
				throw new AddException("이미 존재하는 상품입니다");
			}
		}
		products.add(product);
	}

	@Override
	public Product selectByProdNo(String no) throws FindException{
		for(Product p : products) {
			if(p.getProdNo().equals(no)) {
				return p;
			}
		}
		throw new FindException("상품이 없습니다");
	}

	@Override
	public Object selectAll() throws FindException {
		if(products.size() == 0) {
			throw new FindException("상품이 한개도 없습니다");
		}
		return products;
	}

	@Override
	public void update(Product p) throws ModifyException {
		for(Product savedP : products) {
			if(savedP.getProdNo().equals(p.getProdNo())) {
				if(p.getProdName() != null) {
					savedP.setProdName(p.getProdName());
				}
				if(p.getProdPrice() != 0) {
					savedP.setProdPrice(p.getProdPrice());
				}
				return;
			}
		}
		throw new ModifyException("상품이 없습니다");
	}

	@Override
	public void delete(String prodNo) throws RemoveException {
		for(Product savedP : products) {
			if(savedP.getProdNo().equals(prodNo)) {
				products.remove(savedP);
				return;
			}
		}
		throw new RemoveException("상품이 없습니다");
	}
}
import java.io.IOException;
import java.util.List;
import java.util.Properties;

import com.my.exception.AddException;
import com.my.exception.FindException;
import com.my.exception.ModifyException;
import com.my.exception.RemoveException;
import com.my.product.dao.ProductDAOInterface;
import com.my.product.dto.Product;

public class ProductUser {
	java.util.Scanner sc = new java.util.Scanner(System.in); // non-static 변수는 객체가 생성될 때 메모리에 할당된다 그래서 ProductUser user = new ProductUser(); 해줬음
//	ProductDAOArray dao = new ProductDAOArray();
	
//	ProductDAOInterface dao = new ProductDAOArray();	// 업캐스팅해서 쓰자
//	ProductDAOInterface dao = new ProductDAOList();
	
	ProductDAOInterface dao;
	ProductUser(){
//		dao = new ProductDAOList();	// user가 직접 결정하지 않고 프로퍼티스를 통해 클래스 생성해서 쓰기
		Properties env = new Properties();
		try {
			env.load(ProductUser.class.getResourceAsStream("my.properties"));	// ProductDAOArray dao = new ProductDAOArray(); 이렇게 객체 지정해야하는걸, 어떤 객체를 만들지 결정권은 my.properties에게 넘김
			String className = env.getProperty("product.dao");
			Class clazz = Class.forName(className);
//			clazz.newInstance();
			Object obj = clazz.getDeclaredConstructor().newInstance();
			dao = (ProductDAOInterface)obj;
			System.out.println("DAO에서 실제사용된 클래스:" + dao.getClass().getName());
			
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
				
	}
	
	// 추가가 안된 상태에서 코드를 확인하려면 검색부터 해야한다.
	void findAll() {
//		ProductDAO dao = new ProductDAO(); // 저장소가 findAll과 findByProdNo 각각 만들어지기 때문에, 같은 상품 객체를 써야하기 때문에 지역변수로 만들지말고 멤버변수로 만들기  
		System.out.println(">>상품 전체목록<<");	
		try {
//			Product[] all1 = dao.selectAll();
			Object obj = dao.selectAll();
			if(obj instanceof Product[]) {
				Product[] all1 = (Product[])obj;
				for(int i = 0; i<all1.length; i++) {
					Product p = all1[i];
					System.out.println(p.getProdNo() + ":" + p.getProdName() + ":" + p.getProdPrice());
				}
			} else if (obj instanceof List) {
				List<Product> list = (List)obj;
				for(int i = 0; i<list.size(); i++) {
					Product p = list.get(i);
					System.out.println(p.getProdNo() + ":" + p.getProdName() + ":" + p.getProdPrice());
				}
			}

		} catch (FindException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("-----------------------------------");
	}
	
	void findByProdNo() {
//		ProductDAO dao = new ProductDAO();	// 저장소가 findAll과 findByProdNo 각각 만들어지기 때문에, 같은 상품 객체를 써야하기 때문에 지역변수로 만들지말고 멤버변수로 만들기  
		System.out.println(">>상품 번호로 검색<<");
		System.out.print("상품번호를 입력하세요:");
		String prodNo = sc.nextLine(); // String prodNo = this.sc.nextLine(); this가 생략되어있음. 현재 사용중인 객체의 메서드를 찾아감.
		// main 메서드는 String opt = user.sc.nextLine(); 이렇게 씀  참조변수를 user 찾아갔음. user의 메서드를 찾아야함.	
		Product p;
		try {
			p = dao.selectByProdNo(prodNo);
			if(p == null) {
				System.out.println("상품이 없습니다"); 
			}else{
				//출력됨
				System.out.println(p.getProdNo() +"번호 상품의 상품명:" + p.getProdName() + ", 가격:" + p.getProdPrice());	
			}
		} catch (FindException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	// p = this.dao.selectByProdNo("C0002"); this가 생략되어있음
	}
	
	void add() {
		System.out.println(">>상품 추가<<");
		System.out.print("상품번호를 입력하세요:");
		String prodNo = sc.nextLine();
		System.out.print("상품명을 입력하세요:");
		String prodName = sc.nextLine();
		System.out.print("상품가격을 입력하세요:");
		String prodPrice = sc.nextLine();
		
		/* 방법1
		Product p1 = new Product();
		p1.prodNo = prodNo;	
		// p1이 참조하고있는 객체의 멤버변수. 사용자가 직접 대입하다보면 옳지않은 값 세팅할 수 있음. ex)p1.prodPrice = -10;
		// 그래서 접근 못하게 접근제어자 사용필요.
		p1.prodName = prodName;	
		p1.prodPrice = Integer.parseInt(prodPrice);
		//p1.prodPrice : int타입, prodPrice: String	 => 기본형과 참조형은 구조 자체가 다르기 때문에 형변환 불가능하다. 그래서 라이브러리의 도움을 받는다.
		// String -> int로 변환해주는 라이브러리 : int = Integer.parseInt(String);
		// String -> float로 변환해주는 라이브러리 : float = Float.parseFloat(String);
		dao.insert(p1);
		*/
		
		// 방법2 사용자입장에서 생성하기 편하도록 생성자(특수 메서드) 사용. 위의 방법1을 이걸로 줄일 수 있음.
//		Product p = new Product(prodNo, prodName,Integer.parseInt(prodPrice));
//		dao.insert(p);		
		
		// 방법 3
		Product p = new Product(prodNo, prodName,Integer.parseInt(prodPrice));
		try {
			dao.insert(p);		
		} catch (AddException e) {
			e.printStackTrace();
			System.out.println(e.getMessage());	// user의 형태가 콘솔이여서 이거 썼지, GUI였으면 sysout 안썼음.
		}
		
	}
	
	void update() {
		System.out.println(">>상품 수정<<");
		System.out.print("수정할 상품번호를 입력하세요:");
		String prodNo = sc.nextLine();
		System.out.print("수정할 상품명을 입력하세요:");
		String prodName = sc.nextLine();
		System.out.print("수정할 상품가격을 입력하세요:");
		String prodPrice = sc.nextLine();
		
		if (prodName.equals("")){
			prodName = null;
		}
		
		Product p = new Product(prodNo, prodName,Integer.parseInt(prodPrice));
		try {
			dao.update(p);
		} catch (ModifyException e) {
			e.printStackTrace();
		}
			
	}
	
	void delete() {
		System.out.println(">>상품 삭제<<");
		System.out.print("삭제할 상품번호를 입력하세요:");
		String prodNo = sc.nextLine();
		try {
			dao.delete(prodNo);
		} catch (RemoveException e) {
			e.printStackTrace();
		}
	}
		
	
	public static void main(String[] args) {
		ProductUser user = new ProductUser();
//		user.sc.nextInt();//숫자값
//		user.sc.nextFloat();; //실수값
//		user.sc.next(); // 토큰단위로 읽음
//		user.sc.nextLine(); // 줄바꿈 단위로 읽음, 줄단위로 입력된 값을 반환해주는 메서드
		
		// 반복의 횟수, 반복 최종도달해야하는 값이 결정되있으면 for문 사용하는게 좋으나
		// 반복횟수가 정해져있지 않은 반복문은 while이 적절하다.
		while(true) {
			System.out.println("작업을 선택하세요: 상품전체목록-1, 상품번호로검색-2, 상품추가-3, 상품수정-4, 상품삭제-5, 종료-9;");
			String opt = user.sc.nextLine();
		
			if(opt.equals("1")) {
				user.findAll();
			} else if(opt.equals("2")) {
				user.findByProdNo();				
			} else if(opt.equals("3")) {
				user.add();
			} else if(opt.equals("4")) {
				user.update();
			} else if(opt.equals("5")) {
				user.delete();
			} else if(opt.equals("9")) {
				break;
			}
		}		
	}
}

'언어 > Java' 카테고리의 다른 글

Properties 예시  (0) 2023.08.08
ArrayList, HashSet, HashMap 예시  (0) 2023.08.08
Product 예제 2  (0) 2023.08.04
제네릭(element generic), ArrayList, HashSet 예시  (0) 2023.08.04
향상된 for문  (0) 2023.08.04