본문 바로가기
코딩도전기/MVC

CODO Day18_JAVA_MVC(Abstract(추상화))

by 코도꼬마 2023. 2. 24.

Abstract(추상화)

  • OOP의 4대 특징 중 하나
  • 공통되는 특성을 추출하고 불필요한 정보를 제거단순화시키는 것

 

 

추상 클래스

  • 추상 메서드를 사용해 꼭 구현해야하는 메서드 등의 규격을 만들 수 있음
  • 실체 클래스(concrete class)는 추상 클래스(abstract class)를 상속
  • 자식 외에는 추상 클래스를 객체화 시킬 수 없음
  • 추상화 class 및 method를 선언하기 위해서는 abstract라는 키워드를 붙여야함
      WHY?  추상 클래스와 일반 클래스를 구분해주기 위해 / 추상 메소드는 {몸통}이 없는 형태이기 때문
  • 추상화클래스를 상속받으면 추상화 클래스의 기능을 실체 클래스에서 사용 할 수 있음
  • 추상클래스를 상속 받으면 추상메서드를 강제로 override 하게 됨 
    >> 추상메서드(abstract method)를 통해 꼭 구현해야하는(override해야하는) 메서드를 규격화 시킬 수 있음
  • 지금까지 사용했던 HttpServlet도 추상클래스임  |  HttpServlet에서도 최소 post와 get 방식에는 override해줘야함

 

추상 메서드

  • 꼭 구현해야하는 메서드를 규격화 시킬 수 있음
  • 특정한 메서드를 강제로 override 해야 할 경우 추상메서드로 만들어줌
  • 형태만 있고 몸체는 없는 method  :  String  jump(job); (실행내용X)

 

실생활 예제

  • 어떤 게임에서 직업(클래스)를 추가하여 관리 프로그램을 만들 예정
  • 모든 클래스(직업)는 스킬 사용, 아이템 사용 기능이 필수로 있어야 함
  • 스킬과 아이템 사용은 직업마다 다른 기능을 구현해야 하고, Jump 기능은 클래스 별로 차이가 없음
  • 모든 클래스는 skill()과 useItem()은 반드시 구현해야 하는 상황

Written by zer0box

  • StandardModel(추상클래스)
    • 추상클래스에는 일반메서드와 추상메서드가 있음
      1.일반메서드(그대로 사용)     
      2.추상메서드 : 몸체{실행내용}가 없는 메서드(추상클래스를 상속받으면 반드시 오버라이드 해야함)
package kr.com.web.model;

public abstract class StandardModel {

	//일반 메서드
	public String jump(String job) {
		return job+"가 점프한다";
	}	
    
	//추상 메서드
	public abstract String skill(String job);
	
	public abstract String useItem(String job);
}

 

  • Tanker
    • 추상클래스를 상속받으면 추상메서드는 강제로 오버라이드 됨(규격이기 때문/없으면 에러남)
    • 꼭 필요한 기능을 구현하도록 할 때 유용
package kr.com.web.model;

public class Tanker extends StandardModel {

	@Override
	public String skill(String job) {		
		return job + "가 적들을 도발하는 스킬 사용";
	}

	@Override
	public String useItem(String job) {		
		return job + "가 방어력을 올리는 아이템 사용";
	}
}

 

  • Dealer
package kr.com.web.model;

public class Dealer extends StandardModel {

	@Override
	public String skill(String job) {		
		return job + "가 적들을 공격하는 스킬 사용";
	}

	@Override
	public String useItem(String job) {		
		return job + "가 공격력을 올리는 아이템 사용";
	}
}

 

  • Healer
package kr.com.web.model;

public class Healer extends StandardModel {

	@Override
	public String skill(String job) {		
		return job + "가 대상을 치유하는 스킬 사용";
	}

	@Override
	public String useItem(String job) {		
		return job + "가 치유력을 올리는 아이템 사용";
	}
}

 

  • index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
<style></style>
</head>
<body>
	<form action="">
		클래스 선택 : 
		<select name="class">
			<option value="탱커">탱커</option>
			<option value="딜러">딜러</option>
			<option value="힐러">힐러</option>
		</select>
		행동 선택 : 
		<select id="action">
			<option value="use">아이템사용</option>
			<option value="skill">스킬사용</option>
			<option value="jump">점프</option>
		</select>
		<!-- type="button" : 데이터를 보내지 않고 버튼 역할만 하도록 -->
		<button type="button" onclick="go()">실행</button>
	</form>
	${result}
</body>
<script>
	function go() {
	//console.log('click');
	//1.#action인 값을 가져와서 form의 action 속성에 넣는다.
	var action = $('#action').val();
	//console.log(action);
	$('form').attr('action', action);
	
	//2.form태그를 submit을 이용하여 전송한다.
	$('form').submit();
	}
</script>
</html>

 

  • GameController
package kr.co.web.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.com.web.model.Dealer;
import kr.com.web.model.Healer;
import kr.com.web.model.Tanker;

//일반적으로는 하나의 요청을 하나의 컨트롤러 클래스가 받음
//하지만 다음과 같이 urlPatterns = {}를 이용해 여러요청을 받을 수 있음
@WebServlet(urlPatterns = {"/use","/skill","/jump"})

public class GameController extends HttpServlet {

	//HttpServlet은 추상클래스
	//통신규격을 잡기 위한 클래스(예 : doGet(), doPost())

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		String job = req.getParameter("class"); //파라메터 값은 잘 가져옴
		System.out.println("job = " + job);

		//{"/use","/skill","/jump"} 중 어떤 요청으로 왔는지 확인 가능한가?
		//1.전체 주소를 가져온다.
		String uri = req.getRequestURI();
		System.out.println(uri);  // /04_absClass/use
		//2.이 주소에서 컨텍스트 경로를 빼준다
		String ctx = req.getContextPath();
		System.out.println(ctx);  // /04_absClass
		String addr = uri.substring(ctx.length());
		System.out.println("uri - ctx = " + addr);  // /use
		String result = "";

		switch (job) {
			case "탱커":
				//추상클래스는 자식 외에는 객체화 시킬 수 없음
				//StandardModel model = new StandardModel();
				Tanker tanker = new Tanker();
				
				if(addr.equals("/skill")){
					result = tanker.skill(job);
				}else if(addr.equals("/use")) {
					result = tanker.useItem(job);
				}else {
					result = tanker.jump(job);
				}
				System.out.println(result);
				break;
	
			case "딜러":
				Dealer dealer = new Dealer();
				
				if(addr.equals("/skill")){
					result = dealer.skill(job);
				}else if(addr.equals("/use")) {
					result = dealer.useItem(job);
				}else {
					result = dealer.jump(job);
				}
				break;
	
			case "힐러":
				Healer healer = new Healer();
				if(addr.equals("/skill")){
					result = healer.skill(job);
				}else if(addr.equals("/use")) {
					result = healer.useItem(job);
				}else {
					result = healer.jump(job);
				}
				break;
		}
		System.out.println(result);
		
		req.setAttribute("result", result);
		RequestDispatcher dis = req.getRequestDispatcher("index.jsp");
		dis.forward(req, resp);
	}	

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {

		super.doPost(req, resp);  // 오버라이드해서 사용할 경우 삭제해주어야함
	}
}

 

 

 

Interface*

  • 서로 다른 요소들의 접점을 의미  :  특정 기능을 이용하기 위한 접점 역할
  • Interface는 사용방법을 정의  :  사용방법은 곧 규격을 의미
  • Interface는 객체화 불가능(class가 아니기 때문)
  • 기본적으로 추상화 메서드 사용
  • Interface를 통해서도 특정기능 사용에 대한 규격 설정 가능

 

 

Interfaceabstract class차이

  • Interface도 추상화 메서드를 통해 공동작업 시 규격을 잡아주는 역할을 함
  • Interface는 abstract class와 차이점도 많지만 유사한 부분도 많음

 

  • StandardInter(인터페이스)
    • interface는 객체화가 되지 않아 가질 수 있는 멤버는 추상메서드 밖에 없음(jdk 1.7까지는)
    • jdk 1.8부터 일반메서드도 사용 가능(default 키워드를 붙여줘야함)
    • 인터페이스에서는 추상메서드에 abstract가 붙지 않음(추상메서드 밖에 사용하지 못하기 때문)
package kr.co.web.model;

public interface StandardInter {
	
	//추상메서드
	public String jump(String job);  
	public String skill(String job);
	public String useItem(String job);
	
	//일반메서드
	public default String jump2(String job) {
		return job + "가 2단 점프를 한다";
	}
}

 

  • Tanker
    • interface는 상속이 아닌 구현(implement) 받음
    • interface도 추상메서드를 강제 오버라이드 
package kr.co.web.model;

public class Tanker implements StandardInter {

	@Override
	public String jump(String job) {		
		return job + "가 점프한다";
	}

	@Override
	public String skill(String job) {		
		return job + "가 방어기술을 사용한다";
	}

	@Override
	public String useItem(String job) {		
		return job + "가 방어력 강화 아이템을 사용한다";
	}
}

 

  • Dealer
package kr.co.web.model;

public class Dealer implements StandardInter {

	@Override
	public String jump(String job) {
		return job + "가 점프한다";
	}

	@Override
	public String skill(String job) {
		return job + "가 공격기술을 사용한다";
	}

	@Override
	public String useItem(String job) {
		return job + "가 공격력 강화 아이템을 사용한다";
	}
}

 

  • Healer
package kr.co.web.model;

public class Healer implements StandardInter {

	@Override
	public String jump(String job) {
		return job + "가 점프한다";
	}

	@Override
	public String skill(String job) {
		return job + "가 상대방을 치유한다";
	}

	@Override
	public String useItem(String job) {
		return job + "가 치유력 강화 아이템을 사용한다";
	}
}

 

  • index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
<style></style>
</head>
<body>
	<form action="">
		클래스 선택 : 
		<select name="class">
			<option value="탱커">탱커</option>
			<option value="딜러">딜러</option>
			<option value="힐러">힐러</option>
		</select>
		행동 선택 : 
		<select id="action">
			<option value="use">아이템사용</option>
			<option value="skill">스킬사용</option>
			<option value="jump">점프</option>
		</select>
		<!-- type="button" : 데이터를 보내지 않고 버튼 역할만 하도록 -->
		<button type="button" onclick="go()">실행</button>
	</form>
	${result}
</body>
<script>
	function go() {
	//console.log('click');

	var action = $('#action').val();
	//console.log(action);
    
	$('form').attr('action', action);
	
	$('form').submit();
	}
</script>
</html>

 

  • Controller
package kr.co.web.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.co.web.model.Dealer;
import kr.co.web.model.Healer;
import kr.co.web.model.Tanker;

@WebServlet(urlPatterns = {"/use","/skill","/jump"})
public class Controller extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
		throws ServletException, IOException {

		String job = req.getParameter("class");
		System.out.println(job);

		String uri = req.getRequestURI();
		System.out.println(uri);
		String cxt = req.getContextPath();
		System.out.println(cxt);

		String addr = uri.substring(cxt.length());
		System.out.println(addr);
		String result = "";

		switch (job) {
		case "탱커":
			Tanker tk = new Tanker();

			if(addr.equals("/skill")) {
				result = tk.skill(job);
			}else if(addr.equals("/use")){
				result = tk.useItem(job);
			}else{
				result = tk.jump(job);
			}			
			//System.out.println(result);
			break;

		case "딜러":
			Dealer dl = new Dealer();

			if(addr.equals("/skill")) {
				result = dl.skill(job);
			}else if(addr.equals("/use")){
				result = dl.useItem(job);
			}else{
				result = dl.jump(job);
			}	
			break;
			
		case "힐러":
			Healer hl = new Healer();
			
			if(addr.equals("/skill")) {
				result = hl.skill(job);
			}else if(addr.equals("/use")){
				result = hl.useItem(job);
			}else{
				result = hl.jump(job);
			}	
			break;
		}
		
		System.out.println(result);
		
		req.setAttribute("result", result);
		RequestDispatcher dis = req.getRequestDispatcher("index.jsp");
		dis.forward(req, resp);
	}
}