๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
BackEnd๐ŸŒฑ/Java

[Java] ์ธํ„ฐํŽ˜์ด์Šค(interface) ์ด ์ •๋ฆฌ

by dkswnkk 2022. 3. 30.

์„œ๋ก 

Spring ๊ณต๋ถ€ํ•˜๋˜ ์ค‘ interface๋ถ€๋ถ„์— ๋Œ€ํ•ด ์ดํ•ด๊ฐ€ ๋ถ€์กฑํ•œ ๊ฒƒ ๊ฐ™์•„ ์ž์„ธํ•˜๊ฒŒ ํ•œ๋ฒˆ ์ •๋ฆฌํ•ด ๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋ชฉ์ฐจ
1. ์ธํ„ฐํŽ˜์ด์Šค๋ž€?
2. ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ž‘์„ฑ ๋ฐฉ๋ฒ•
3. ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ƒ์†
4. ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„
5. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•œ ๋‹คํ˜•์„ฑ
6. ์ธํ„ฐํŽ˜์ด์Šค์˜ ์žฅ์ 

 

1. ์ธํ„ฐํŽ˜์ด์Šค๋ž€?

์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ผ์ข…์˜ ์ถ”์ƒ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ถ”์ƒ ํด๋ž˜์Šค์ฒ˜๋Ÿผ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ–์ง€๋งŒ ์ถ”์ƒ ํด๋ž˜์Šค๋ณด๋‹ค ์ถ”์ƒํ™” ์ •๋„๊ฐ€ ๋†’์•„์„œ ์ถ”์ƒ ํด๋ž˜์Šค์™€ ๋‹ฌ๋ฆฌ ๋ชธํ†ต์„ ๊ฐ–์ถ˜ ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ ๋˜๋Š” ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋ฅผ ๊ตฌ์„ฑ์›์œผ๋กœ ๊ฐ€์งˆ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์˜ค์ง "์ถ”์ƒ ๋ฉ”์„œ๋“œ"์™€ "์ƒ์ˆ˜"๋งŒ์„ ๋ฉค๋ฒ„๋กœ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ๋ถ€๋ถ„์ ์œผ๋กœ๋งŒ ์™„์„ฑ๋œ '๋ฏธ์™„์„ฑ ์„ค๊ณ„๋„'๋ผ๊ณ  ํ•œ๋‹ค๋ฉด, ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ตฌํ˜„๋œ ๊ฒƒ์€ ์•„๋ฌด๊ฒƒ๋„ ์—†๊ณ  ๋ฐ‘๊ทธ๋ฆผ๋งŒ ๊ทธ๋ ค์ ธ ์žˆ๋Š” '๊ธฐ๋ณธ ์„ค๊ณ„๋„'๋ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 ์ธํ„ฐํŽ˜์ด์Šค๋„ ์ถ”์ƒ ํด๋ž˜์Šค์ฒ˜๋Ÿผ ์™„์„ฑ๋˜์ง€ ์•Š์€ ๋ถˆ์™„์ „ํ•œ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ์ž์ฒด๋งŒ์œผ๋กœ ์‚ฌ์šฉ๋˜๊ธฐ๋ณด๋‹ค๋Š” ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•˜๋Š”๋ฐ ๋„์›€์„ ์ค„ ๋ชฉ์ ์œผ๋กœ ์ž‘์„ฑ๋ฉ๋‹ˆ๋‹ค.

 

2. ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ž‘์„ฑ ๋ฐฉ๋ฒ•

์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ํ‚ค์›Œ๋“œ๋กœ class ๋Œ€์‹  interface๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ๋งŒ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  interface์—๋„ ํด๋ž˜์Šค์™€ ๊ฐ™์ด ์ ‘๊ทผ์ œ์–ด์ž๋กœ public ๋˜๋Š” default๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

interface ์ธํ„ฐํŽ˜์ด์Šค์ด๋ฆ„{
    public static final ํƒ€์ž… ์ƒ์ˆ˜์ด๋ฆ„ = ๊ฐ’;
    public abstract ๋ฉ”์„œ๋“œ์ด๋ฆ„(๋งค๊ฐœ๋ณ€์ˆ˜๋ชฉ๋ก);
}

 

์ผ๋ฐ˜์ ์ธ ํด๋ž˜์Šค์˜ ๋ฉค๋ฒ„๋“ค๊ณผ ๋‹ฌ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉค๋ฒ„๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ œ์•ฝ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

- ๋ชจ๋“  ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋Š” public static final ์ด์–ด์•ผ ํ•˜๋ฉฐ, ์ด๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค.
- ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋Š” public abstract ์ด์–ด์•ผ ํ•˜๋ฉฐ, ์ด๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค.(๋‹จ, static๋ฉ”์„œ๋“œ์™€ default ๋ฉ”์„œ๋“œ๋Š” JDK1.8๋ถ€ํ„ฐ ์˜ˆ์™ธ)

 

interface PlayingCard {
    public static final int SPADE = 4;
    final int DIAMOND = 3;   // public static final int DIAMOND = 3;
    static int HEART = 2;    // public static final int HEART = 2;
    int CLOVER = 1;          // public static final int CLOVER = 1;

    public abstract String getCardNumber();
    String getCardKing();   // public abstract String getCardKind();
}

์ƒ๋žต๋œ ์ œ์–ด์ž๋Š” ์ปดํŒŒ์ผ ์‹œ์— ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ž๋™์ ์œผ๋กœ ์œ„์™€ ๊ฐ™์ด ์ถ”๊ฐ€ํ•ด ์ค๋‹ˆ๋‹ค.

 

3. ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ƒ์†

์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋กœ๋ถ€ํ„ฐ๋งŒ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํด๋ž˜์Šค์™€๋Š” ๋‹ฌ๋ฆฌ ๋‹ค์ค‘ ์ƒ์†, ์ฆ‰ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋กœ๋ถ€ํ„ฐ ์ƒ์†์„ ๋ฐ›๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.(์ฐธ๊ณ : ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํด๋ž˜์Šค์™€ ๋‹ฌ๋ฆฌ Objectํด๋ž˜์Šค์™€ ๊ฐ™์€ ์ตœ๊ณ  ์กฐ์ƒ์ด ์—†์Šต๋‹ˆ๋‹ค.)

interface Movable {
  /** ์ง€์ •๋œ ์œ„์น˜(x, y)๋กœ ์ด๋™ํ•˜๋Š” ๊ธฐ๋Šฅ์˜ ๋ฉ”์„œ๋“œ */
  void move(int x, int y);
}

interface Attackable {
 /** ์ง€์ •๋œ ๋Œ€์ƒ(u)์„ ๊ณต๊ฒฉํ•˜๋Š” ๊ธฐ๋Šฅ์˜ ๋ฉ”์„œ๋“œ */
  void attack(Unit u);
}

interface Fightable extends Movable, Attackable {}

ํด๋ž˜์Šค์˜ ์ƒ์†๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ž์† ์ธํ„ฐํŽ˜์ด์Šค(Fightable)๋Š” ์กฐ์ƒ ์ธํ„ฐํŽ˜์ด์Šค(Movable, Attackable)์— ์ •์˜๋œ ๋ฉค๋ฒ„๋ฅผ ๋ชจ๋‘ ์ƒ์†๋ฐ›์Šต๋‹ˆ๋‹ค.

 ๊ทธ๋ž˜์„œ Fightable์ž์ฒด์—๋Š” ์ •์˜๋œ ๋ฉค๋ฒ„๊ฐ€ ํ•˜๋‚˜๋„ ์—†์ง€๋งŒ ์กฐ์ƒ ์ธํ„ฐํŽ˜์ด์Šค๋กœ๋ถ€ํ„ฐ ์ƒ์†๋ฐ›์€ ๋‘ ๊ฐœ์˜ ์ถ”์ƒ ๋ฉ”์„œ๋“œ, move(int x, int y)์™€ attack(Unit u)์„ ๋ฉค๋ฒ„๋กœ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

4. ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„

์ธํ„ฐํŽ˜์ด์Šค๋„ ์ถ”์ƒ ํด๋ž˜์Šค์ฒ˜๋Ÿผ ๊ทธ ์ž์ฒด๋กœ๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์—†์œผ๋ฉฐ, ์ถ”์ƒ ํด๋ž˜์Šค๊ฐ€ ์ƒ์†์„ ํ†ตํ•ด ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์™„์„ฑํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ์ธํ„ฐํŽ˜์ด์Šค๋„ ์ž์‹ ์—๊ฒŒ ์ •์˜๋œ ์ถ”์ƒ ๋ฉ”์„œ๋“œ์˜ ๋ชธํ†ต์„ ๋งŒ๋“ค์–ด์ฃผ๋Š” ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 

class ClassName implements InterfaceName {
  // ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜๋œ ์ถ”์ƒ๋ฉ”์„œ๋“œ ๊ตฌํ˜„
}

interface InterfaceName{
}

์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ตฌํ˜„ํ•œ๋‹ค๋Š” ์˜๋ฏธ์˜ ํ‚ค์›Œ๋“œ 'implements'๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์œ„์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

abstract class Fighter implements Fightable {
    public void move(int x, int y) { /* ๋‚ด์šฉ ์ƒ๋žต */ }
}

๋งŒ์ผ ๊ตฌํ˜„ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฉ”์„œ๋“œ ์ค‘ ์ผ๋ถ€๋งŒ ๊ตฌํ˜„ํ•œ๋‹ค๋ฉด, abstract๋ฅผ ๋ถ™์—ฌ์„œ ์œ„์™€ ๊ฐ™์ด ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

class Fighter extends Unit implements Fightable {
    public void move(int x, int y) { /* ๋‚ด์šฉ ์ƒ๋žต */ }
    public void attack(Unit u) { /* ๋‚ด์šฉ ์ƒ๋žต */ }
}

๊ทธ๋ฆฌ๊ณ  ์œ„์™€ ๊ฐ™์ด ์ƒ์†๊ณผ ๊ตฌํ˜„์„ ๋™์‹œ์— ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•œ๋ฒˆ ์•„๋ž˜์˜ ์ „์ฒด ์ฝ”๋“œ๋ฅผ ํ•œ๋ฒˆ ์˜ˆ์‹œ๋กœ ๋“ค์–ด ์ •๋ฆฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

class FighterTest {
    public static void main(String[] args) {
        Fighter f = new Fighter();

        if (f instanceof Unit) {
            System.out.println("f๋Š” Unitํด๋ž˜์Šค์˜ ์ž์†์ž…๋‹ˆ๋‹ค.");
        }
        if (f instanceof Fightable) {
            System.out.println("f๋Š” Fightable์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.");
        }
        if (f instanceof Movable) {
            System.out.println("f๋Š” Movable์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.");
        }
        if (f instanceof Attackable) {
            System.out.println("f๋Š” Attackable์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.");
        }
        if (f instanceof Object) {
            System.out.println("f๋Š” Objectํด๋ž˜์Šค์˜ ์ž์†์ž…๋‹ˆ๋‹ค.");
        }
    }
}

class Fighter extends Unit implements Fightable {
    public void move(int x, int y) { /* ๋‚ด์šฉ ์ƒ๋žต */ }

    public void attack(Unit u) { /* ๋‚ด์šฉ ์ƒ๋žต */ }
}

class Unit {
    int currentHP;    // ์œ ๋‹›์˜ ์ฒด๋ ฅ
    int x;            // ์œ ๋‹›์˜ ์œ„์น˜(x์ขŒํ‘œ)
    int y;            // ์œ ๋‹›์˜ ์œ„์น˜(y์ขŒํ‘œ)
}

interface Fightable extends Movable, Attackable {
}

interface Movable {
    void move(int x, int y);
}

interface Attackable {
    void attack(Unit u);
}

์œ„ ์ฝ”๋“œ์˜ ์ถœ๋ ฅ ๊ฒฐ๊ณผ
์œ„ ์ฝ”๋“œ์˜ ํด๋ž˜์Šค์™€ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ„์˜ ๊ด€๊ณ„

์‹ค์ œ๋กœ Fighterํด๋ž˜์Šค๋Š” Unitํด๋ž˜์Šค๋กœ๋ถ€ํ„ฐ ์ƒ์†๋ฐ›๊ณ  Fightable์ธํ„ฐํŽ˜์ด์Šค๋งŒ์„ ๊ตฌํ˜„ํ–ˆ์ง€๋งŒ, Unitํด๋ž˜์Šค๋Š” Objectํด๋ž˜์Šค์˜ ์ž์†์ด๊ณ , Fightable์ธํ„ฐํŽ˜์ด์Šค๋Š” Attackable๊ณผ Movable์ธํ„ฐํŽ˜์ด์Šค์˜ ์ž์†์ด๋ฏ€๋กœ Fighterํด๋ž˜์Šค๋Š” ์ด ๋ชจ๋“  ํด๋ž˜์Šค์™€ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ž์†์ด ๋˜๋Š” ์…ˆ์ด ๋ฉ๋‹ˆ๋‹ค.

 

5. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•œ ๋‹คํ˜•์„ฑ

์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์˜ ์กฐ์ƒ์ด๋ผ ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž…์˜ ์ฐธ์กฐ ๋ณ€์ˆ˜๋กœ ์ด๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž…์œผ๋กœ์˜ ํ˜• ๋ณ€ํ™˜๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. 

Fightable f = new Fighter();

์˜ˆ๋ฅผ ๋“ค์–ด ์œ„์™€ ๊ฐ™์ด ์ธํ„ฐํŽ˜์ด์Šค Fightable์„ ํด๋ž˜์Šค Fighter๊ฐ€ ๊ตฌํ˜„ํ–ˆ์„ ๋•Œ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด Fighter์ธ์Šคํ„ด์Šค๋ฅผ Fightableํƒ€์ž…์˜ ์ฐธ์กฐ ๋ณ€์ˆ˜๋กœ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

void attack(Fightable f){
    // ๋‚ด์šฉ ์ƒ๋žต
}

๋”ฐ๋ผ์„œ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์œ„์™€ ๊ฐ™์ด ๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ํƒ€์ž…์œผ๋กœ๋„ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž…์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๊ฐ–๋Š” ์˜๋ฏธ๋Š” ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ attack๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ Fightable์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋„˜๊ฒจ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

class Fighter extends Unit implements Fightable {
    public void move(int x, int y) { /* ๋‚ด์šฉ ์ƒ๋žต */}
    public void attack(Fightable f) { /* ๋‚ด์šฉ ์ƒ๋žต */}
}

ํ•œ๋ฒˆ ์œ„์˜ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Fightable์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ Fighterํด๋ž˜์Šค๊ฐ€ ์žˆ์„ ๋•Œ, attack๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ Fighter์ธ์Šคํ„ด์Šค๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, attack(new Fighter())์™€ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. 

 

Fightable method() {
  //...
  Figther fighter = new Fighter();
  return fighter;
}

๊ทธ๋ฆฌ๊ณ  ์œ„์™€ ๊ฐ™์ด ๋ฉ”์„œ๋“œ์˜ ๋ฆฌํ„ด ํƒ€์ž…์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค์˜ ํƒ€์ž…์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ ์—ญ์‹œ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌํ„ด ํƒ€์ž…์ด ์ธํ„ฐํŽ˜์ด์Šค๋ผ๋Š” ๊ฒƒ์€ ๋ฉ”์„œ๋“œ๊ฐ€ ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์œ„์˜ ์ฝ”๋“œ์—์„œ๋Š” method()์˜ ๋ฆฌํ„ด ํƒ€์ž…์ด Fightable์ธํ„ฐํŽ˜์ด์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”์„œ๋“œ์˜ return๋ฌธ์—์„œ Fightable์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ Fighterํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜์˜ ๋‹คํ˜•์„ฑ ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ํ•œ๋ฒˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

interface Parseable {
    // ๊ตฌ๋ฌธ ๋ถ„์„์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
    public abstract void parse(String fileName);
}

class ParserManager {
    // ๋ฆฌํ„ดํƒ€์ž…์ด Parseable์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.
    public static Parseable getParser(String type) {
        if (type.equals("XML")) {
            return new XMLParser();
        } else {
            Parseable p = new HTMLParser();
            return p;
            // return new HTMLParser();
        }
    }
}

class XMLParser implements Parseable {
    public void parse(String fileName) {
        /* ๊ตฌ๋ฌธ ๋ถ„์„์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ ๋Š”๋‹ค. */
        System.out.println(fileName + "- XML parsing completed.");
    }
}

class HTMLParser implements Parseable {
    public void parse(String fileName) {
        /* ๊ตฌ๋ฌธ ๋ถ„์„์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ ๋Š”๋‹ค. */
        System.out.println(fileName + "-HTML parsing completed.");
    }
}

class ParserTest {
    public static void main(String args[]) {
        Parseable parser = ParserManager.getParser("XML");
        parser.parse("document.xml");
        parser = ParserManager.getParser("HTML");
        parser.parse("document2.html");
    }
}

์ธจ๋ ฅ ๊ฒฐ๊ณผ

๋งŒ์ผ ๋‚˜์ค‘์— ์ƒˆ๋กœ์šด ์ข…๋ฅ˜์˜ NewXMLParserํด๋ž˜์Šค๊ฐ€ ๋‚˜์™€๋„ ParserTestํด๋ž˜์Šค๋Š” ๋ณ€๊ฒฝํ•  ํ•„์š” ์—†์ด, ParserManagerํด๋ž˜์Šค์˜ getParser๋ฉ”์„œ๋“œ์—์„œ 'return newXMLParser(); ๋Œ€์‹  'return new NewXMLParser();'๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์žฅ์ ์€ ํŠนํžˆ ๋ถ„์‚ฐ ํ™˜๊ฒฝ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ๊ทธ ์œ„๋ ฅ์„ ๋ฐœํœ˜ํ•˜๋Š”๋ฐ, ์‚ฌ์šฉ์ž ์ปดํ“จํ„ฐ์— ์„ค์น˜๋œ ํ”„๋กœ๊ทธ๋žจ์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ์„œ๋ฒ„ ์ธก์˜ ๋ณ€๊ฒฝ๋งŒ์œผ๋กœ๋„ ์‚ฌ์šฉ์ž๊ฐ€ ์ƒˆ๋กœ ๊ฐœ์ •๋œ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

6. ์ธํ„ฐํŽ˜์ด์Šค์˜ ์žฅ์ 

๊ทธ๋ ‡๋‹ค๋ฉด ์™œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ• ๊นŒ์š”? ๊ทธ ์žฅ์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ๊ฐœ๋ฐœ ์‹œ๊ฐ„์„ ๋‹จ์ถ•์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
  • ํ‘œ์ค€ํ™”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์„œ๋กœ ๊ด€๊ณ„์—†๋Š” ํด๋ž˜์Šค๋“ค์—๊ฒŒ ๊ด€๊ณ„๋ฅผ ๋งบ์–ด ์ค„ ์ˆ˜ ์žˆ๋‹ค.
  • ๋…๋ฆฝ์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค ์žฅ์  ์˜ˆ์ œ ์ฝ”๋“œ

class RepairableTest {
    public static void main(String[] args) {
        Tank tank = new Tank();
        Dropship dropship = new Dropship();

        Marine marine = new Marine();
        SCV scv = new SCV();

        scv.repair(tank);    // SCV๊ฐ€ Tank๋ฅผ ์ˆ˜๋ฆฌํ•˜๋„๋ก ํ•œ๋‹ค.
        scv.repair(dropship);
//	scv.repair(marine);  // ์ฃผ์„์„ ํ’€๋ฉด ์ปดํŒŒ์ผ ์—๋Ÿฌ ๋ฐœ์ƒ
    }
}

interface Repairable {
}

class GroundUnit extends Unit {
    GroundUnit(int hp) {
        super(hp);
    }
}

class AirUnit extends Unit {
    AirUnit(int hp) {
        super(hp);
    }
}

class Unit {
    int hitPoint;
    final int MAX_HP;

    Unit(int hp) {
        MAX_HP = hp;
    }
    //...
}

class Tank extends GroundUnit implements Repairable {
    Tank() {
        super(150);        // Tank์˜ HP๋Š” 150์ด๋‹ค.
        hitPoint = MAX_HP;
    }

    public String toString() {
        return "Tank";
    }
    //...
}

class Dropship extends AirUnit implements Repairable {
    Dropship() {
        super(125);        // Dropship์˜ HP๋Š” 125์ด๋‹ค.
        hitPoint = MAX_HP;
    }

    public String toString() {
        return "Dropship";
    }
    //...
}

class Marine extends GroundUnit {
    Marine() {
        super(40);
        hitPoint = MAX_HP;
    }
    //...
}

class SCV extends GroundUnit implements Repairable {
    SCV() {
        super(60);
        hitPoint = MAX_HP;
    }

    void repair(Repairable r) {
        if (r instanceof Unit) {
            Unit u = (Unit) r;
            while (u.hitPoint != u.MAX_HP) {
                /* Unit์˜ HP๋ฅผ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค. */
                u.hitPoint++;
            }
            System.out.println(u.toString() + "์˜ ์ˆ˜๋ฆฌ๊ฐ€ ๋๋‚ฌ์Šต๋‹ˆ๋‹ค.");
        }
    }
    //...
}

์ถœ๋ ฅ๊ฒฐ๊ณผ

์œ„ ์ฝ”๋“œ๋Š” ์Šคํƒ€ํฌ๋ž˜ํ”„ํŠธ ๊ฒŒ์ž„ ์œ ๋‹›์„ ๋Œ€์ƒ์œผ๋กœ ํด๋ž˜์Šค๋กœ ๊ตฌํ˜„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. 

์ƒ์† ๊ณ„์ธต๋„

๋ชจ๋“  ์œ ๋‹›๋“ค์˜ ์ตœ๊ณ  ์กฐ์ƒ์€ Unitํด๋ž˜์Šค์ด๊ณ  ์œ ๋‹›์˜ ์ข…๋ฅ˜๋Š” ์ง€์ƒ ์œ ๋‹›(GroundUnit)๊ณผ ๊ณต์ค‘ ์œ ๋‹›(AirUnit)์œผ๋กœ ๋‚˜๋ˆ„์–ด์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ง€์ƒ ์œ ๋‹›์—๋Š” Marine, SCV, Tank๊ฐ€ ์žˆ๊ณ , ๊ณต์ค‘ ์œ ๋‹›์œผ๋กœ๋Š” Dropship์ด ์žˆ์Šต๋‹ˆ๋‹ค. SCV์—๊ฒŒ Tank, Dropship๊ณผ ๊ฐ™์€ ๊ธฐ๊ณ„ํ™” ์œ ๋‹›์„ ์ˆ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด repair()๋ฅผ ์ •์˜ํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

void repair(Tank tank) {
  // Tank๋ฅผ ์ˆ˜๋ฆฌํ•œ๋‹ค.
}

void repair(Dropship dropship) {
  // Dropship์„ ์ˆ˜๋ฆฌํ•œ๋‹ค.
}

์ด๋Ÿฐ ์‹์œผ๋กœ ์ˆ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์œ ๋‹›์˜ ๊ฐœ์ˆ˜๋งŒํผ ๋‹ค๋ฅธ ๋ฒ„์ „์˜ ์˜ค๋ฒ„๋กœ๋”ฉ๋œ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ํƒ€์ž…์„ ์ด ๋“ค์˜ ๊ณตํ†ต ์กฐ์ƒ์œผ๋กœ ํ•˜๋ฉด ์ข‹๊ฒ ์ง€๋งŒ Dropship์€ ๊ณตํ†ต์กฐ์ƒ์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๊ณตํ†ต์กฐ์ƒ์˜ ํƒ€์ž…์œผ๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•œ๋‹ค๊ณ  ํ•ด๋„ ์•„๋ž˜์™€ ๊ฐ™์ด ์ตœ์†Œํ•œ 2๊ฐœ์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ํ•„์š”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

void repair(GroundUnit groundUnit) {
  // ์ง€์ƒ์œ ๋‹› ์ˆ˜๋ฆฌ
}

void repair(AirUnit airUnit) {
  // ๊ณต์ค‘์œ ๋‹› ์ˆ˜๋ฆฌ
}

๊ทธ๋ฆฌ๊ณ  GroundUnit์˜ ์ž์† ์ค‘์—๋Š” Marine๊ณผ ๊ฐ™์ด ๊ธฐ๊ณ„ํ™” ์œ ๋‹›์ด ์•„๋‹Œ ํด๋ž˜์Šค๋„ ํฌํ•จ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— repair๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์œผ๋กœ GroundUnit์€ ๋ถ€์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. 

 ํ˜„์žฌ์˜ ์ƒ์†๊ด€๊ณ„์—์„œ๋Š” ์ด๋“ค์˜ ๊ณตํ†ต์ ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋•Œ๋ฌธ์— ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ธฐ์กด์˜ ์ƒ์†์ฒด๊ณ„๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ์ด๋“ค ๊ธฐ๊ณ„ํ™” ์œ ๋‹›์— ๊ณตํ†ต์ ์„ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด Repairable์ด๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•˜๊ณ  ์ˆ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ธฐ๊ณ„ํ™” ์œ ๋‹›์—๊ฒŒ ์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

interface Repairable {
}

// ์ง€์ƒ์œ ๋‹› ์ƒ์†, ์ˆ˜๋ฆฌ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„
class SCV extends GroundUnit implements Repairable {
    // ...
}

// ์ง€์ƒ์œ ๋‹› ์ƒ์†, ์ˆ˜๋ฆฌ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„
class Tank extends GroundUnit implements Repairable {
    // ...
}

// ๊ณต์ค‘์œ ๋‹› ์ƒ์†, ์ˆ˜๋ฆฌ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„
class Dropship extends AirUnit implements Repairable {
    // ...
}

์ด์ œ ์ด 3๊ฐœ์˜ ํด๋ž˜์Šค์—๋Š” ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค๋Š” ๊ณตํ†ต์ ์ด ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค Repairable์— ์ •์˜๋œ ๊ฒƒ์€ ์•„๋ฌด๊ฒƒ๋„ ์—†๊ณ , ๋‹จ์ง€ ์ธ์Šคํ„ด์Šค์˜ ํƒ€์ž… ์ฒดํฌ์—๋งŒ ์‚ฌ์šฉ๋  ๋ฟ์ž…๋‹ˆ๋‹ค. Repairable์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ์ƒ์†๊ณ„์ธต๋„๋ฅผ ๊ทธ๋ ค๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ƒ์† ๊ณ„์ธต๋„

repair๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ r์€ Repairableํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— ์ธํ„ฐํŽ˜์ด์Šค Repairable์— ์ •์˜๋œ ๋ฉค๋ฒ„๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Repairable์—๋Š” ์ •์˜๋œ ๋ฉค๋ฒ„๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ด ํƒ€์ž…์˜ ์ฐธ์กฐ ๋ณ€์ˆ˜๋กœ๋Š” ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์€ ์•„๋ฌด๊ฒƒ๋„ ์—†์Šต๋‹ˆ๋‹ค.

 ๊ทธ๋ž˜์„œ instanceof์—ฐ์‚ฐ์ž๋กœ ํƒ€์ž…์„ ์ฒดํฌํ•œ ๋’ค ์บ์ŠคํŒ…ํ•˜์—ฌ Unitํด๋ž˜์Šค์— ์ •์˜๋œ hitPoint์™€ MAX_HP๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๊ทธ๋‹ค์Œ์—” ์œ ๋‹›์˜ ํ˜„์žฌ ์ฒด๋ ฅ(hitPoint)์ด ์œ ๋‹›์ด ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ์ตœ๊ณ  ์ฒด๋ ฅ(MAX_HP)์ด ๋  ๋•Œ๊นŒ์ง€ ์ฒด๋ ฅ์„ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 Marine์€ Repairable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ SCVํด๋ž˜์Šค์˜ repair๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ Marine์„ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํŒŒ์ผ ์‹œ์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋Œ“๊ธ€