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()은 반드시 구현해야 하는 상황
- 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를 통해서도 특정기능 사용에 대한 규격 설정 가능
Interface와 abstract 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);
}
}
'코딩도전기 > MVC' 카테고리의 다른 글
CODO Day23_JAVA_MVC(Exception) (0) | 2023.03.06 |
---|---|
CODO Day22_JAVA_MVC(String) (0) | 2023.03.06 |
CODO Day20~21_JAVA_MVC(추상화의 장점/다형성) (0) | 2023.02.28 |
CODO Day19_JAVA_MVC(Interface 다중 구현/익명객체/Interface 상속) (0) | 2023.02.27 |
CODO Day17_JAVA_MVC(Model2/상속*) (0) | 2023.02.23 |