Cafe.Java.다형성문제.지사별 판매관리시스템
아래 문제를 풀때 기능 설계와 상세설계를 하여서 검사받고 구현하세요.
1. 판매관리
지사는 서울지사, 경인지사, 강원지사, 제주지사가 있다.
각 지사별 제품명 : 컴퓨터, 프린터가 있다. 컴퓨터가격은 200만원 프린터가격은 50만원이다.
출력하고 싶은 것은 지사별 판매량을 입력받아서 매출현황을 모두 보고 싶다.
------------------------
판매량관리 프로젝트
-------------------------
1. 입력 2. 출력 3. 종료
선택?(1)
지사는?
1. 서울지사, 2. 경인지사, 3. 강원지사 4. 제주지사
선택은?(1)
제품은? 컴퓨터
서울지사 컴퓨터 판매량은? 10
계속 입력하시겠습니까?(y/n)
만약 y이면
지사는?
1. 서울지사, 2. 경인지사, 3. 강원지사 4. 제주지사
선택은?(1)
서울지사 판매량은? 10
계속 입력하시겠습니까?(y/n)
만약 n이면
------------------------
판매량관리 프로젝트
-------------------------
1. 입력 2. 출력 3. 종료
선택?(2)
-----------------------------------------------
각 지사별 판매 현황
-------------------------------------------------
지사명 제품명 제품가격 판매량 매출현황
-------------------------------------------------
서울지사 컴퓨터 2000000 10 200000000
강원지사 프린터 500000 5 2500000
제주지사 컴퓨터 2000000 1 20000000
---------------------------------------------------
1단계 - 기본 설계
각 클래스를 설계한다. 조상 클래스와 자손클래스를 구분한다.
메인클래스에 동작할 내용을 작성한다.
비즈니스 클래스에 매출현황을 구할 메소드를 설계한다.
2단계 - 상세설계
기본 설계를 바탕으로 실제적인 클래스명이나 멤버명을 짓고 접근제한자를 명시하여 구체적으로 설계한다.
3단계 - 구현 단계
상세설계를 보고 프로그램을 구현한다.
요구사항 분석
1. 지사별 상품(컴퓨터, 프린터)의 판매량을 입력받아 각 값을 저장한다.
2. 연산 : 사실상 매출현황만 계산하면 되는데, 간단한 가격 X 판매량 연산이기 때문에 3에서 해도 될 것 같다.
3. 전체 데이터를 출력한다. 지사별로 제품명, 제품가격, 판매량, 매출현황을 출력한다.
Ver1

사실 클래스와 메소드, 필드만 대략적으로 떠오르는대로 설계해두고 바로 코드작성에 들어갔다.
클래스 : Business Prodcut Branch - Seoul Gyeongin Gangwon Jeju로 계획

문제 및 폐기이유
제품에 관한 정보를 Product에만 저장하고 입력시스템도 Product에 넣다보니 Product 클래스가 비대해졌다.
비즈니스클래스 - Product 클래스 - Branch 클래스 - 다형성 객체까지 넘나들며 지사별 데이터를 넣어주기가 너무 번거로워졌다.
입력받은 값을 검증하고 적절하지 않을 때 첫화면으로 돌아가는 게 아니라, 같은 메소드를 다시 호출하도록 하고 싶었는데 각 지사객체(seoul, ...)를 매개변수를 가진 메소드이기 때문에 불가능하다.
방안 :
해설을 전부 듣지는 못했지만, 지사별 데이터를 저장하기 위해서 Product의 자료에 가까워 보일지라도 Branch에 넣을 필요가 있다는 걸 인식
클래스 설계부터 다시 고민해야한다.
Ver2
요구사항 분석 : 입력, 연산, 출력
1. 지사별 상품(컴퓨터, 프린터)의 판매량을 입력받아 각 값을 저장한다.
- 세 개의 데이터값이 하나의 객체에 저장되어야 하기 때문에 객체를 Product, Branch로 나누지 않고 "지사별"에 초점을 두어 Branch에 저장한다.
2. 연산 : 가격은 상수, 입력받은 판매량을 가지고 곱하기 연산만 하면 되는데, 메소드로 처리하면 될것 같다.
3. 전체 데이터를 출력한다. 지사별로 제품명, 제품가격, 판매량, 매출현황을 출력한다. → 마찬가지로 기존에 객체에 저장한 값을 불러오고, 2연산의 리턴값을 불러오면 되기 때문에 따로 객체를 생성하지 않고 메소드로 처리하겠다.
클래스 설계
1. Branch : branchName[ ], productSales[ ] - 0은 컴퓨터 1은 프린터라고 전제하고 판매량을 저장, productPrice(final),ProductName[]
- Seoul, Gyeongin, Gangwon, JejuBranch
2. Main : Branch의 자식클래스 객체 생성, input(), printSalesInfo(), revenue()
코드작성
1. Branch
지사명과 상품명은 종류는 많지 않은데, 반복적으로 쓸 예정이라 배열처리했다.
BranchCode는 쓸 일이 있을 줄 알았는데, 쓰지 않게되어 주석처리했다.
productSales[0] : 컴퓨터의판매량 [1]:프린터의 판매량 가격은 상수
package ver2;
public class Branch {
String branchName[] = {"서울지사","경인지사","강원지사","제주지사"};
// Branch branchCode[] = new Branch[4]; //0서울=branchCode[0] 1경인 2강원 3제주
String productName[] = {"컴퓨터", "프린터"};
int productSales[] = new int[2];
final int productPrice[] = {2000000, 500000};
Branch() {
}
}
2. 실행클래스
switch문의 case를 쓸 때 가독성을 위해 모두 메소드 호출로 대신한다.
애먹었던 부분이 많았다.
1. sl, gi, gw,jj를 추상화할 수 없을까? 아직 미해결
2. SalesInput() 계속 입력에 대한 답변을 String으로 받아놓고 비교 연산자로 조건문을 작성하고 있었음. equals() 메소드를 사용하여 해결
3. SalesInput() 계속 입력하다가 n라고 대답할 때, return문을 한번만 주었더니 전에 입력한 횟수만큼 "계속 입력하시겠습니까?"가 출력됨
즉 SalesInput()이 일정횟수 반복되고 있었음.
if(y) { input() }에 return문을 주지 않아 input()를 수행하고 돌아올 때 do while반복문이 실행되었기 때문
조건에 대한 수행문이 다른 메소드의 호출일 때, 돌아올 때 메소드가 정상적으로 끝날 수 있도록 return문을 작성함으로써 해결
4. 1과 상통하는 어려움. sl, gi, gw, jj를 추상화할 수 없기 때문에, 각각의 자식객체에 저장된 판매량을 하나의 배열로 만들어 반복문에 활용할 수 없었음
결국 값이 몇 없으니 직접 상품별로 배열을 만들어 {sl.~~, gi~~,gw~~,jj~~}로 직접 값을 입력하고 그 다음은 반복문으로 해결했다.
package ver2;
import java.util.Scanner;
public class Business {
static Scanner sc = new Scanner(System.in); //여러 메소드에서 사용할것이기 때문에 메인메소드 밖에서static으로 선언한다.
static Branch br = new Branch();
//다형성 객체 생성 : 각각의 지사에서 판매된 데이터들은 그때그때 새로운 값이 아닌 누적값으로 저장되어야 한다.따라서 반복문 밖에서 생성한다.
static Branch sl = new SeoulBranch();
static Branch gi = new GyeoninBranch();
static Branch gw = new GangwonBranch();
static Branch jj = new JejuBranch();
public static void main(String[] args) {
boolean flag = true;
do {
int selectMenu;
System.out.println("-------------------");
System.out.println(" 판매량 관리 프로젝트");
System.out.println("-------------------");
System.out.println("1.입력 2.출력 3.종료");
System.out.println("선택>");
selectMenu = sc.nextInt();
switch(selectMenu) {
case 1: input(); break;
case 2: printSalesInfo(); break;
case 3: System.out.println("프로그램을 종료합니다."); flag = false;
default : System.out.println("잘못 입력하셨습니다"); break;
}
} while(flag);
}
private static void input() {
System.out.println("어느 지사 소속이십니까?\n1.서울지사 2.경인지사 3.강원지사 4.제주지사");
System.out.println("선택>");
int branchInput = sc.nextInt();
if(branchInput > 4 || branchInput <1)
input();
else {
System.out.println();
salesInput(branchInput);
}
}
private static void salesInput(int branchInput) {
int productInput; //0 컴퓨터 1 프린터
int salesInput;
System.out.println("제품은? 1.컴퓨터 2.프린터");
productInput = sc.nextInt();
System.out.println(br.branchName[branchInput-1] + " " + br.productName[productInput-1] + " 판매량은?");
//si, gi, gw, jj를 추상화하지 못해, 경우의 수가 많지 않기 때문에 직접 참조변수를 써줬음
salesInput = sc.nextInt();
switch(branchInput) {
case 1: sl.productSales[productInput-1] += salesInput; break;
case 2: gi.productSales[productInput-1] += salesInput; break;
case 3: gw.productSales[productInput-1] += salesInput; break;
case 4: jj.productSales[productInput-1] += salesInput; break;
default:
}
boolean flag = true;
do {
System.out.println("계속 입력하시겠습니까?(y/n)");
String continueInput = sc.next();
if(continueInput.equals("y")) {input(); return;}
else if(continueInput.equals("n")) flag= false; //return으로 쓸수도 있음
else continue;
} while(flag);
}
private static void printSalesInfo() {
System.out.println("------------------------------");
System.out.println(" 각 지사별 판매 현황");
System.out.println("------------------------------");
System.out.println("지사명\t제품명\t제품가격\t판매량\t매출현황");
System.out.println("------------------------------");
int computerSales[] = {sl.productSales[0], gi.productSales[0], gw.productSales[0], jj.productSales[0]};
int printerSales[] = {sl.productSales[1], gi.productSales[1], gw.productSales[1], jj.productSales[1]};
for(int i=0; i<br.branchName.length; i++) {
if(computerSales[i] != 0 )
System.out.println(br.branchName[i] + "\t" + br.productName[0]
+ "\t" + br.productPrice[0] + "\t" + computerSales[i] + "\t"+ (br.productPrice[0]*(long)computerSales[i]));
if(printerSales[i] != 0 )
System.out.println(br.branchName[i] + "\t" + br.productName[1]
+ "\t" + br.productPrice[1] + "\t" + printerSales[i] + "\t" + (br.productPrice[1]*(long)printerSales[i]));
}
}
}
3. 자식클래스: 모두동일(Seoul, Gyeongin,Gangwon,Jeju)
public class SeoulBranch extends Branch{
}
*Tip
1. 메인클래스의 가독성을 높이기 위해 반복문 안의 메소드를 하단으로 따로 뺀다.
2. 조건에 대한 수행문이 다른 메소드의 호출일 때, 돌아올 때 메소드가 정상적으로 끝날 수 있도록 return문을 작성한다.
'Java > CodePractice' 카테고리의 다른 글
| Ch12 확인문제 (0) | 2021.03.31 |
|---|---|
| Ch9 중첩클래스와 중첩 인터페이스 (0) | 2021.03.21 |
| Ch7 상속 문제(합,차,곱) (0) | 2021.03.14 |
| Ch7 - 다형성 TireEx (0) | 2021.03.11 |