MVC 패턴
M: Model => VO, DAO 데이터를 담당하는 부분
V: View => 사람 눈에 보이는 화면을 담당하는 부분
C: Controller => 기능을 담당하는 부분
main 메소드에 코드를 몰아 넣으면 유지보수 및 협업이 힘듦
Run 클래스
ackage com.kh.chap01.list.part02.mvc.run;
import com.kh.chap01.list.part02.mvc.view.MusicView;
public class Run {
// 프로그램의 시작점: 사용자가 프로그램이 시작되었을 때 가장 먼저 볼 화면을 담당할 메소드를 호출하는 역할
public static void main(String[] args) {
MusicView mv = new MusicView();
mv.mainMenu();
}
}
MusicView 클래스
package com.kh.chap01.list.part02.mvc.view;
import java.util.ArrayList;
import java.util.Scanner;
import com.kh.chap01.list.part02.mvc.controller.MusicController;
import com.kh.chap01.list.part02.mvc.model.vo.Music;
// View: 시각적인 요소 (사용자가 보게 될 화면)
// 출력문과 입력문을 사용
public class MusicView {
// 전역변수
private Scanner sc = new Scanner(System.in);
// => 얘를 insertMusic 메소드 안에서 호출하면 메소드가 끝날 때 함께 사라져 버림!
private MusicController mc = new MusicController();
// 사용자가 프로그램 시작 시 가장 처음 보여지는 화면: 메인화면
// 메인화면을 담당할 메소드
public void mainMenu() {
while(true) {
System.out.println("*** Welcome 별밤 ***");
System.out.println("1. 새로운 곡 추가");
System.out.println("2. 곡 전체 조회");
System.out.println("3. 특정 곡 검색");
System.out.println("4. 특정 곡 삭제");
System.out.println("5. 특정 곡 수정");
System.out.println("0. 프로그램 종료");
System.out.println("---------------------");
System.out.print("메뉴 입력: ");
int menu = sc.nextInt();
sc.nextLine();
switch(menu) {
case 1 :
insertMusic();
break;
case 2 :
selectMusicList();
break;
case 3 :
searchMusic();
break;
case 4 :
deleteMusic();
break;
case 5 :
updateMusic();
break;
case 0 : System.out.println("프로그램을 종료합니다.");
return; // 이때 return을 써야 나를 호출했던 main으로 돌아가기 때문에 종료됨
default : System.out.println("잘못된 메뉴입니다. 다시 입력해 주세요.");
}
}
}
// 1. 새로운 곡을 추가시킬 수 있는 화면
public void insertMusic() {
System.out.println("== 새로운 곡 추가 ==");
System.out.print("곡명 입력: ");
String title = sc.nextLine();
System.out.print("가수명: ");
String artist = sc.nextLine();
// 추가해 주세요 요청 => Controller 클래스와 메소드를 호출
// 클래스대변할이름.메소드명(넘겨줄값);
// mc.insertMusic(title, artist);
// System.out.println("성공적으로 추가되었습니다.");
// (+) 추가, 삭제, 수정처럼 성공 여부로 판단하고 싶다면?
int result = mc.insertMusic(title, artist);
// (+) 추가 성공 판별
if(result > 0) {
System.out.println("성공적으로 추가되었습니다.");
} else {
System.out.println("곡 추가에 실패했습니다.");
}
}
// 2. 전체 곡을 조회할 수 있는 화면
public void selectMusicList() {
System.out.println("== 곡 전체 조회 ==");
// 전체 리스트를 조회해 주세요 요청 => Controller 클래스의 메소드 호출
ArrayList<Music> list = mc.selectMusicList();
if(list.isEmpty()) { // 리스트가 비어 있을 경우
System.out.println("현재 존재하는 곡이 없습니다.");
} else {
for(int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
// 3. 특정 곡을 검색할 수 있는 화면
public void searchMusic() {
System.out.println("== 특정 곡 검색 ==");
System.out.print("검색할 곡명 키워드: ");
String keyword = sc.nextLine();
// 검색해 주세요 요청 => Controller 클래스의 메소드 호출
ArrayList<Music> searched = mc.searchMusic(keyword);
System.out.println("검색 결과");
if(searched.isEmpty()) { // 검색 결과가 없다면
} else { // 검색 결과가 있다면
for(Music m : searched) {
System.out.println(m);
}
}
}
// 4. 특정 곡을 삭제할 수 있는 화면
public void deleteMusic() {
System.out.println("== 특정 곡 삭제 ==");
System.out.print("삭제할 곡명: ");
String title = sc.nextLine();
// 삭제해 주세요 요청 => Controller 클래스의 메소드 호출
// 삭제 진행 여부도 리턴받을 것
// 리턴받을자료형 리턴받을값 = 클래스대변할이름.메소드명(넘겨줄값);
int result = mc.deleteMusic(title);
// 삭제 진행 여부 검사
if(result > 0) { // 양수값 == 삭제 진행됨
System.out.println("성공적으로 삭제되었습니다.");
} else { // 삭제할 곡을 찾지 못함
System.out.println("삭제할 곡을 찾지 못했습니다.");
}
}
// 5. 특정 곡을 수정할 수 있는 화면
public void updateMusic() {
System.out.println("== 특정 곡 수정 ==");
// 뭐를 어떻게 수정해야 하는지 언급
// => 기존 곡명, 수정할 곡명, 수정할 가수명 입력받기
System.out.print("기존 곡명: ");
String title = sc.nextLine();
System.out.print("수정 내용(곡명): ");
String upTitle = sc.nextLine();
System.out.print("수정 내용(가수명): ");
String upArtist = sc.nextLine();
// 수정해 주세요 요청 => Controller 클래스의 메소드 호출
// 수정 여부 리턴받기 (int)
int result = mc.updateMusic(title, upTitle, upArtist);
// 수정 여부 판별
if(result > 0) { // 수정이 진행됨
System.out.println("성공적으로 수정되었습니다.");
} else { // 수정할 곡을 찾지 못함
System.out.println("수정할 곡을 찾지 못했습니다.");
}
}
}
MusicController 클래스
package com.kh.chap01.list.part02.mvc.controller;
import java.util.ArrayList;
import com.kh.chap01.list.part02.mvc.model.vo.Music;
public class MusicController {
// 음악을 보관할 수 있는 저장소를 전역변수로 빼 두고 두고두고 사용할 목적
// => 얘를 insertMusic 메소드 안에서 호출하면 메소드가 끝날 때 함께 사라져 버림!
ArrayList<Music> list = new ArrayList<>();
{
// 초기화 블록
list.add(new Music("강남스타일", "싸이"));
list.add(new Music("테스형!", "나훈아"));
}
// 1. 새로운 곡 추가 요청 시 실행할 메소드
// public void insertMusic(String title, String artist) {
// (+) 반환형 void -> int로 수정
public int insertMusic(String title, String artist) {
// (+) before 구하기
int before = list.size();
list.add(new Music(title, artist)); // 내가 원하는 값으로 생성된 객체가 list에 들어감
// 여기까지 실행되고 나면 나를 호출했던 view의 mc.insertMusic(title, artist);로 돌아감
// (+) 추가, 삭제, 수정처럼 성공 여부로 판단하고 싶다면?
// (+) 추가된 데이터의 개수를 리턴
// (+) 필요한 항목
// (+) 추가된 후 ArrayList의 크기 - 추가되기 전 ArrayList의 크기,
// (+) add 후의 사이즈 - before
return list.size() - before; // 0이라면 추가가 안 된 것
}
// 2. 전체 곡 조회 요청 시 실행할 메소드
public ArrayList<Music> selectMusicList() {
return list;
}
// 3. 특정 곡 검색 요청 시 실행할 메소드
public ArrayList<Music> searchMusic(String keyword) {
// 검색 기능: 해당 키워드가 포함된 것들은 모두 조회
// (1) 검색된 결과물을 담을 변수 셋팅(0개일 수도 있고, 1개일 수도 있고, 여러 개일수도 있음)
ArrayList<Music> searched = new ArrayList<>(); // 현재 빈 상태
// (2) 반복문을 돌려가며 "포함"된 것이 있나 검사해야 함
// => 포함된 내용물이라면 검색된 결과물을 담을 수 있는 변수에 담아 두기
for(int i = 0; i < list.size(); i++) {
// 문자열의 일치관계를 검사할 수 있는 메소드: 문자열.equals(비교할문자열) => true/false
// 문자열의 포함관계를 검사할 수 있는 메소드: 문자열.contains(검사할문자열)
// => 문자열 안에 검사할 문자열이 포함되어 있다면 true / 포함되지 않았다면 false
if(list.get(i).getTitle().contains(keyword)) { // 포함되어 있을 경우
searched.add(list.get(i));
}
}
// (3) 검색된 결과를 View단으로 리턴하기
return searched;
}
// 4. 특정 곡 삭제 요청 시 실행될 메소드
public int deleteMusic(String title) {
int result = 0;// 삭제가 진행된 개수를 나타내는 변수
// 반복문을 통해 곡 제목이 일치하는지 검사
for(int i = 0; i < list.size(); i++) {
if(list.get(i).getTitle().equals(title)) { // 곡 제목이 일치한다면
// list.remove(i);
// remove는 해당 목록을 없앤 후 뒤에 있는 값들을 당겨 주는 역할까지 겸함
// 1번째 값을 없애면 2번째 값이 1번째 값에 올 테고, 그대로 증감식으로 올라가 버리면 2 -> 1번째로 옮겨진 값은 for문에 걸리지 않음
list.remove(i--); // 후위연산을 추가해 주면 일단 i 그대로 계산하고, 있을 때 -1 한 값부터 다시 확인하기 때문에 해결 가능!
result++;
}
}
// result 리턴
return result; // 0일 수도 있고(삭제된 게 없을 경우), 양수값일 수도 있음(삭제된 게 있을 경우)
}
// 5. 특정 곡 수정 요청 시 실행될 메소드
public int updateMusic(String title, String upTitle, String upArtist) {
// (1) 수정된 곡 개수를 받을 변수 세팅
int result = 0;
// (2) 반복문을 통해 제목이 일치하는지 검사 후 일치한다면 곡 정보를 수정
for(int i = 0; i < list.size(); i++) {
if(list.get(i).getTitle().equals(title)) { // 제목이 일치한다면
// 수정하는 방법 2가지
// 1. 비교적 효율적인 방법
/*
list.get(i).setTitle(upTitle);
list.get(i).setArtist(upArtist);
*/
// 2. 비교적 효율적인 방법은 아니지만 오늘 배운 내용을 활용할 수 있는 방법
// => 메모리 영역에 할당이 한 번 더 이루어지긴 함
list.set(i, new Music(upTitle, upArtist));
result++;
}
}
// (3) 결과 반환
return result; // 0일 수도 있고(수정한 곡이 없음), 양수일 수도 있음(수정한 곡의 수)
}
}
Music 클래스
package com.kh.chap01.list.part02.mvc.model.vo;
public class Music {
// 필드부
private String title;
private String artist;
//
public Music() {
super();
}
public Music(String title, String artist) {
super();
this.title = title;
this.artist = artist;
}
//
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
@Override
public String toString() {
return "Music [title=" + title + ", artist=" + artist + "]";
}
}