The Debugging Chronicles : "코드의 미학"
학생부 프로그램03 예제로 알아보는 MVC 패턴 본문
MVC(model view controller)는
사용자 인터페이스, 데이터 및 논리 제어를 구현하는데 널리 사용되는
소프트웨어 디자인 패턴입니다.
소프트웨어의 비즈니스 로직과 화면을 구분하는데 중점을 두고 있다.
이러한 "관심사 분리"는 더 나은 업무의 분리와 향상된 관리를 제공합니다.
Model : 데이터와 비즈니스 로직을 관리
모델은 앱이 포함해할 데이터가 무엇인지를 정의
데이터의 상태가 변경되면, 모델을 일반적으로 뷰에게 알리며 가끔 컨트롤러에게 알리기도 한다.
View : 레이아웃과 화면을 처리
앱의 데이터를 보여주는 방식을 정의
Controller : 모델과 뷰로 명령을 전달
앱의 사용자로부터의 입력에 대한 응답으로 모델 및 뷰를 업데이트하는 로직을 포함
>>>view
package view;
import java.util.ArrayList;
import java.util.Scanner;
import service.model.StudentDTO;
public class StudentView {
static Scanner sc=new Scanner(System.in);
// 출력 부분
// 메뉴 출력
public void printMenu() {
System.out.println("=== 메 뉴 ===");
System.out.println("1. 학생추가");
System.out.println("2. 전체출력");
System.out.println("3. 번호검색");
System.out.println("4. 이름검색");
System.out.println("5. 평균출력");
System.out.println("6. 점수변경");
System.out.println("7. 학생삭제");
System.out.println("0. 프로그램 종료");
System.out.println("==========");
}
// 이름 입력 안내 출력
public void printNameInfo() {
System.out.print("추가할 학생의 이름 입력 >> ");
}
// 성적 입력 안내 출력
public void printScoreInfo() {
System.out.print("추가할 학생의 성적 입력 >> ");
}
// 학생 추가 완료 멘트 출력
public void printAddSuccess() {
System.out.println("학생 추가 완료!");
}
// 전체 목록 출력
public void printAllList(ArrayList<StudentDTO> datas) {
System.out.println("=== 전체 목록 ===");
for(StudentDTO data : datas) {
System.out.println(data);
}
System.out.println("===============");
}
// 목록이 비어있을 때 출력
public void printEmpty() {
System.out.println("출력할 데이터가 없습니다!");
}
// 검색할 학생 번호 입력 안내 출력
public void printNumInfo() {
System.out.print("검색할 학생의 번호 입력 >> ");
}
// 검색 결과 출력
public void printSearchList(StudentDTO data) {
if(data==null) {
System.out.println("검색 결과가 없습니다!");
return;
}
System.out.println("=== 검색 결과 ===");
System.out.println(data);
System.out.println("===============");
}
// 검색 결과 여러명 출력
public void printSearchList(ArrayList<StudentDTO> datas) {
if(datas.size() == 0) {
System.out.println("검색 결과가 없습니다!");
return;
}
System.out.println("=== 검색 결과 ===");
for(StudentDTO data : datas) {
System.out.println(data);
}
System.out.println("===============");
}
// 삭제할 이름 입력 출력
public void printDeleteInfo() {
System.out.println("삭제할 학생의 학번 입력 >> ");
}
// 삭제 성공, 실패 출력
public void printIsDelete(boolean result) {
if(result) {
System.out.println("삭제 성공!");
return;
}
System.out.println("삭제 실패..");
}
// 점수 업데이트 성공 출력
public void printIsUpdate(boolean result) {
if(result) {
System.out.println("점수 업데이트 성공!");
return;
}
System.out.println("점수 업데이트 실패..");
}
// 평균 출력
public void printAvg(double avg) {
// 학생이 많아질수록, 성적이 다양해질 수록
// 즉, 데이터가 많아지면 view에 로직이 있으면 느려진다.
// 따라서 평균 로직을 백엔드에 위치 시킨다.
System.out.println("평균은 " + avg + "입니다.");
}
// 이름 검색 출력
public void printNameSearchInfo() {
System.out.println("검색할 이름을 입력 >> ");
}
// 입력 부분
// 메뉴 입력
public int inputAction() {
int action=sc.nextInt();
return action;
}
// 이름 입력
public String inputName() {
String name;
while(true){
name=sc.next();
System.out.println("정말 " + name +"으로 입력하시겠습니까? (Y/N)");
String answer = sc.next();
if(answer.equals("Y")) {
break;
}
this.printNameInfo();
}
return name;
}
// 점수 입력
public int inputScore() {
int score=sc.nextInt();
return score;
}
// 번호 입력
public int inputNum(int lastPK) {
int num;
while(true) {
num=sc.nextInt();
if(101 <= num && num <= lastPK) {
break;
}
System.out.println("다시 입력해주세요.");
}
return num;
}
}
>>> service model
>>DTO
package service.model;
// MVC 패턴에서 data를 VO, DTO라고 함
// 지금까지 불러왔던 데이터
public class StudentDTO {
// 멤버 변수
private int num;
private String name;
private int score;
// 평균 변수를 선언해 준다.
private double avg;
public double getAvg() {
return avg;
}
public void setAvg(double avg) {
this.avg = avg;
}
// 게터,세터
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "StudentDTO [num=" + num + ", name=" + name + ", score=" + score + "]";
}
}
>> DAO
package service.model;
import java.util.ArrayList;
// MVC 패턴에서 DBMS 파트를 DAO라고 함
// 매니지먼트 시스템
public class StudentDAO {
// 멤버 변수
private ArrayList<StudentDTO> datas;
// 같은 패키지 안에서는 import가 필요없음
// JAVA x ▷ MySQL, Oracle로 이동될 예정
// 생성자
// 미리 3명의 학생을 만들어 놓음
public StudentDAO() {
System.out.println(" service.model.StudentDAO StudentDAO() 생성자 시작");
// 학생 객체를 담을 새로운 datas 배열을 만듦
datas = new ArrayList<StudentDTO>();
// 샘플 데이터 or 기존 데이터 생성
// 학생 객체1을 만듦
StudentDTO data1=new StudentDTO();
data1.setNum(101);
data1.setName("오리아나");
data1.setScore(50);
// 생성된 학생1을 datas 배열에 넣어줌
datas.add(data1);
// 학생2
StudentDTO data2=new StudentDTO();
data2.setNum(102);
data2.setName("모르가나");
data2.setScore(89);
datas.add(data2);
// 학생3
StudentDTO data3=new StudentDTO();
data3.setNum(103);
data3.setName("티모");
data3.setScore(67);
datas.add(data3);
System.out.println(" service.model.StudentDAO StudentDAO() 생성자 종료");
}
// 함수
// CUD는 output이 boolean
// 데이터의 처리가 성공했는지 실패했는지 알아야하기 때문에
public boolean insert(int num, String name, int score) {
System.out.println(" service.model.StudentDAO insert() 생성자 시작");
// DBMS에 data를 추가 == AL에 DTO 추가
// 객체를 생성, 멤버변수 값들을 넣어줌
StudentDTO data = new StudentDTO();
data.setNum(num);
data.setName(name);
data.setScore(score);
// 데이터를 넣어줌 학생부 목록에 넣어줌
datas.add(data);
System.out.println(" service.model.StudentDAO insert() 생성자 종료");
return true;
}
public boolean update(int num, int score) {
// 삭제하려는 학번을 받아옴
// 배열은 현재 배열을 사용
// 해당 학번의 학생을 찾아봄
System.out.println(" service.model.StudentDAO update() 생성자 시작");
for(int i = 0 ; i < datas.size(); i++) {
if(datas.get(i).getNum() != num) {
continue;
}
datas.get(i).setScore(score);
System.out.println(" service.model.StudentDAO update() 성공");
return true;
}
System.out.println(" service.model.StudentDAO update() 실패");
return false;
}
public boolean delete(int num) {
// 삭제하려는 학번을 받아옴
// 배열은 현재 배열을 사용
// 해당 학번의 학생을 찾아봄
System.out.println(" service.model.StudentDAO delete() 생성자 시작");
for(int i = 0 ; i < datas.size(); i++) {
if(datas.get(i).getNum() != num) {
continue;
}
datas.remove(i);
System.out.println(" service.model.StudentDAO delete() 성공");
return true;
}
System.out.println(" service.model.StudentDAO delete() 실패");
return false;
}
// R : output인 여러개인 경우 AL, 하나인 경우 DTO
// 전체 출력
public ArrayList<StudentDTO> selectAll(){
// 데이터 전체 목록을 넘기면 됨
System.out.println(" service.model.StudentDAO selectAll()");
return this.datas;
/*ArrayList<StudentDTO> datas = new ArrayList<StudentDTO>();
return datas;
// null이 반환되는 경우는 없다.
// 다만, .size(0가 0일 수는 있다.*/
}
// 이름 검색
public ArrayList<StudentDTO> selectAll(String name){
System.out.println(" service.model.StudentDAO selectAll() 시작");
ArrayList<StudentDTO> al = new ArrayList<StudentDTO>();
for(StudentDTO data : this.datas) {
if(data.getName().contains(name)) {
al.add(data);
}
}
System.out.println(" service.model.StudentDAO selectAll() 종료");
return al;
}
// 한 명만 출력
// 학번을 인자로 받음
public StudentDTO selectOne(int num){
System.out.println(" service.model.StudentDAO selectOne() 생성자 시작");
// datas(학생부) 전체를 확인하여 일치하는 학번이 있는지 검사
for(StudentDTO data : this.datas) {
// 만약 일치한다면
if(data.getNum() == num) {
System.out.println(" service.model.StudentDAO selectOne() 데이터 일치");
// 일치하는 데이터를 반환
return data;
}
}
System.out.println(" service.model.StudentDAO selectOne() 데이터 불일치");
// 없다면 공백을 반환
return null;
}
// 평균값을 계산
public StudentDTO avg() {
System.out.println(" service.model.StudentDAO selectOne() 시작 : 평균");
int sum = 0;
for(StudentDTO data:datas){
sum += data.getScore();
}
double avg = sum*1.0 / datas.size();
// 함수의 반환타입이 객체이기 때문에 객체를 담기 위해 객체를 생성
StudnetDTO dto = new StudentDTO();
dto.setAvg(avg);
System.out.println(" service.model.StudentDAO selectOne() 종료 : 평균");
return dto;
}
}
>>>service controller
package service.controller;
import java.util.ArrayList;
import service.model.StudentDTO;
import service.model.StudentDAO;
import view.StudentView;
public class StudentController {
// 멤버변수
private StudentDAO model; // 학생부
private StudentView view; // 출력할 것들 목록
private int PK; // 학번을 넣어줄 정수 변수
// 생성자
public StudentController() {
this.model=new StudentDAO();
this.view=new StudentView();
this.PK=104; // 샘플 데이터가 이미 3명이 있기 때문에 104번부터 선택
}
// 사용자(Client)에게 [M과 V를 조합해서] 서비스를 제공하는 역할
public void start() {
while (true) {
// 메뉴 출력
view.printMenu();
// 메뉴 선택값을 반환받음
int action=view.inputAction();
if(action == 1) { // 학생 추가
view.printNameInfo(); // 이름을 입력받으라는 멘트
String name=view.inputName(); // 입력을 받음
view.printScoreInfo(); // 점수를 입력받으라는 멘트
int score=view.inputScore(); // 점수를 입력받음
// 값을 입력받고 제대로 입력받았는지 확인하는 값을 반환
boolean flag=model.insert(PK++, name, score);
if(flag) { // 만약 성공했다면
view.printAddSuccess(); // 성공 멘트
}
else {
// 실패했습니다.
System.out.println("실패했습니다.");
}
}
else if(action == 2){ // 전체 출력
// 학생부에 있는 데이터를 전부 반환받아(selectAll) 새로운 배열 datas에 넣어줌
// <StudentDTO>은 배열 타입
ArrayList<StudentDTO> datas=model.selectAll();
view.printAllList(datas); // 전부 출력
}
else if(action == 3){ // 번호 검색
view.printNumInfo(); // 번호를 입력하라는 멘트
int num = view.inputNum(PK); // 번호를 입력받음
// 입력받은 번호를 인자로 검색(출력) 실행
// view에서 출력
// DAO에서 인자를 받아 값을 반환
view.printSearchList(model.selectOne(num));
}
else if(action == 4){ // 이름 겁색
// 이름 입력 안내 (view)
view.printNameSearchInfo();
// 이름 입력 받음, 입력값 확인 (view)
String name = view.inputName();
// 입력값이 포함된 이름이 있나 확인 (model)
ArrayList<StudentDTO> al = model.selectAll(name);
// 출력(view)
view.printAllList(al);
}
else if(action == 5){ // 평균 출력
/*
방법 1. selectOne - DAO에서 평균값을 구하고 값을 가져오기
StudentDTO data = model.selectOne();
double avg = data.getAvg();
*/
// 방법 2. selectAll - controller 에서 데이터를 직접가공
ArrayList<StudentDTO> datas = model.selectAll();
int sum=0;
for(StudentDTO data:datas){
sum += data.getScore();
}
double avg = sum*1.0/datas.size();
view.print14(avg);
}
else if(action == 6){ // 점수 변경
// 학번을 입력하라는 안내(view)
view.printNumInfo();
// 학번을 입력받음(view)
int num = view.inputNum(PK);
// 변경할 점수 입력 안내(view)
view.printScoreInfo();
// 변경할 점수를 입력받음(view)
int score = view.inputScore();
// 학번에 맞는 학생을 찾아서 점수 변경 (model)
model.update(num, score);
}
else if(action == 7){ // 학생 삭제
// 학번을 입력하라는 안내
view.printDeleteInfo();
// 학번을 입력받음
int num = view.inputNum(PK);
// 학생을 찾아서 삭제 시도
boolean flag = model.delete(num);
// 삭제 성공 실패 출력(view)
view.printIsDelete(flag);
}
else if(action == 0){
break;
}
}
}
}
>>client
package client;
import service.controller.StudentController;
public class Client02 {
public static void main(String[] args) {
// 학생부 프로그램
StudentController app = new StudentController();
app.start();
}
}
'JAVA > 자바 수업 내용' 카테고리의 다른 글
pivot (0) | 2024.07.29 |
---|---|
결합도와 응집도 (0) | 2024.07.17 |
예제로 알아보는 자바의 인터페이스 (0) | 2024.07.15 |
객체 지향 언어 특징 - 추상화(Abstraction) (0) | 2024.07.12 |
객체 지향 언어 특징 - 캡슐화(Encapsulation) (0) | 2024.07.12 |