** ๐Ÿ“Œ 0๋‹จ๊ณ„ ํ•ต์‹ฌ ์š”์•ฝ: ์ธํ„ฐํŽ˜์ด์Šค ์™„๋ฒฝ ์ •๋ฆฌ! **

โœ… ์ธํ„ฐํŽ˜์ด์Šค๋ž€?

โœ… ํด๋ž˜์Šค์™€ ์ฐจ์ด์ 

โœ… ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ฃผ์š” ํŠน์ง•

โœ… ์ธํ„ฐํŽ˜์ด์Šค์˜ ํ™œ์šฉ

โœ… ์‹ค๋ฌด์—์„œ์˜ ์˜ˆ์‹œ

๐Ÿ‘‰ ๊ฒฐ๋ก : ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ฐ•๋ ฅํ•œ ์„ค๊ณ„ ๋„๊ตฌ๋กœ, ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(OOP)์˜ ํ•ต์‹ฌ! ๐Ÿš€

๐Ÿ“Œ 1~7๋‹จ๊ณ„ ๋ณธ๋ฌธ ์ •๋ฆฌ: ์ธํ„ฐํŽ˜์ด์Šค ๊ฐœ๋…๋ถ€ํ„ฐ ์‹ค๋ฌด ์ ์šฉ๊นŒ์ง€ ์™„๋ฒฝ ์ •๋ฆฌ!


1๏ธโƒฃ ํŒจํ‚ค์ง€: โ€œํ•™๊ต ๊ฑด๋ฌผโ€์„ ๋งŒ๋“ ๋‹ค! ๐Ÿซ

๐Ÿ’ก ํŒจํ‚ค์ง€(Package)๋Š” ๊ด€๋ จ๋œ ํด๋ž˜์Šค๋“ค์„ ํด๋”์ฒ˜๋Ÿผ ์ •๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“Œ ํŒจํ‚ค์ง€ ๊ตฌ์กฐ ์˜ˆ์ œ (school ํŒจํ‚ค์ง€)


school/
 โ”œโ”€โ”€ Person.java        // ๋ชจ๋“  ์‚ฌ๋žŒ์˜ ๊ณตํ†ต ์†์„ฑ (๋ถ€๋ชจ ํด๋ž˜์Šค)
 โ”œโ”€โ”€ HomeworkDoer.java  // ์ˆ™์ œ๋ฅผ ํ•ด์•ผ ํ•˜๋Š” ์‚ฌ๋žŒ (์ธํ„ฐํŽ˜์ด์Šค)
 โ”œโ”€โ”€ Teacher.java       // ๊ฐ€๋ฅด์ณ์•ผ ํ•˜๋Š” ์‚ฌ๋žŒ (์ธํ„ฐํŽ˜์ด์Šค)
 โ”œโ”€โ”€ Student.java       // ํ•™์ƒ ํด๋ž˜์Šค (์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„)
 โ”œโ”€โ”€ MathTeacher.java   // ์ˆ˜ํ•™ ์„ ์ƒ๋‹˜ ํด๋ž˜์Šค (์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„)
 โ”œโ”€โ”€ SchoolTest.java    // ์‹คํ–‰ํ•˜๋Š” ์ฝ”๋“œ

2๏ธโƒฃ ๋ถ€๋ชจ ํด๋ž˜์Šค(Person): ๋ชจ๋“  ์‚ฌ๋žŒ์˜ ๊ณตํ†ต ์†์„ฑ

๐Ÿ’ก ๋ถ€๋ชจ ํด๋ž˜์Šค๋Š” ๊ณตํ†ต ์†์„ฑ์„ ์ •์˜ํ•ด ์ฝ”๋“œ ์ค‘๋ณต์„ ์ค„์ž„

๐Ÿ“Œ Person.java (๋ถ€๋ชจ ํด๋ž˜์Šค)

package school;

public class Person {
    protected String name;
    protected int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void showInfo() {
        System.out.println("๐Ÿ‘ค ์ด๋ฆ„: " + name + ", ๋‚˜์ด: " + age);
    }
}

โœ” ๊ณตํ†ต ์†์„ฑ: name, age

โœ” ๊ณตํ†ต ๋ฉ”์„œ๋“œ: showInfo() (์ด๋ฆ„๊ณผ ๋‚˜์ด ์ถœ๋ ฅ)


3๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค(HomeworkDoer): โ€œ์ˆ™์ œ๋ฅผ ํ•ด์•ผ ํ•˜๋Š” ์‚ฌ๋žŒโ€

๐Ÿ’ก ์ธํ„ฐํŽ˜์ด์Šค๋Š” โ€œํ•ด์•ผ ํ•˜๋Š” ์ผโ€์„ ์ •์˜ํ•˜๋Š” ๊ทœ์น™

๐Ÿ“Œ HomeworkDoer.java (์ˆ™์ œ ์ธํ„ฐํŽ˜์ด์Šค)

package school;

public interface HomeworkDoer {
    void doHomework();  // ์ˆ™์ œ๋ฅผ ํ•ด์•ผ ํ•˜๋Š” ๊ทœ์น™
}

โœ” โ€œ์ˆ™์ œ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌ๋žŒโ€์€ ๋ฐ˜๋“œ์‹œ doHomework()๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ


4๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค(Teacher): โ€œ๊ฐ€๋ฅด์ณ์•ผ ํ•˜๋Š” ์‚ฌ๋žŒโ€

๐Ÿ’ก ์„ ์ƒ๋‹˜์€ ํ•™์ƒ์„ ๊ฐ€๋ฅด์ณ์•ผ ํ•˜๋ฏ€๋กœ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๊ทœ์น™์„ ์ •์˜

๐Ÿ“Œ Teacher.java (์„ ์ƒ๋‹˜ ์ธํ„ฐํŽ˜์ด์Šค)

package school;

public interface Teacher {
    void teach();  // ๊ฐ€๋ฅด์น˜๋Š” ๊ธฐ๋Šฅ
}

โœ” โ€œ๊ฐ€๋ฅด์น  ์ˆ˜ ์žˆ๋Š” ์‚ฌ๋žŒโ€์€ ๋ฐ˜๋“œ์‹œ teach()๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ


5๏ธโƒฃ ํ•™์ƒ(Student) ๋งŒ๋“ค๊ธฐ ๐ŸŽ’

๐Ÿ’ก ํ•™์ƒ์€ Person(์‚ฌ๋žŒ)์ด๋ฉฐ, HomeworkDoer(์ˆ™์ œํ•ด์•ผ ํ•จ) ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋”ฐ๋ฆ„.

๐Ÿ“Œ Student.java (ํ•™์ƒ ํด๋ž˜์Šค)

package school;

public class Student extends Person implements HomeworkDoer {
    public Student(String name, int age) {
        super(name, age);
    }

    @Override
    public void doHomework() {
        System.out.println("๐Ÿ“š " + name + "๊ฐ€(์ด) ์ˆ™์ œ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค!");
    }
}

โœ” Person์„ ์ƒ์†๋ฐ›์•„ ๊ณตํ†ต ์†์„ฑ(name, age) ์‚ฌ์šฉ

โœ” HomeworkDoer๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ doHomework() ๊ฐ•์ œ ๊ตฌํ˜„


6๏ธโƒฃ ์ˆ˜ํ•™ ์„ ์ƒ๋‹˜(MathTeacher) ๋งŒ๋“ค๊ธฐ ๐Ÿ‘ฉโ€๐Ÿซ

๐Ÿ’ก ์ˆ˜ํ•™ ์„ ์ƒ๋‹˜์€ Person(์‚ฌ๋žŒ)์ด๋ฉฐ, Teacher(๊ฐ€๋ฅด์ณ์•ผ ํ•จ) ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋”ฐ๋ฆ„.

๐Ÿ“Œ MathTeacher.java (์ˆ˜ํ•™ ์„ ์ƒ๋‹˜ ํด๋ž˜์Šค)

package school;

public class MathTeacher extends Person implements Teacher {
    public MathTeacher(String name, int age) {
        super(name, age);
    }

    @Override
    public void teach() {
        System.out.println("๐Ÿ“– " + name + "๊ฐ€(์ด) ์ˆ˜ํ•™์„ ๊ฐ€๋ฅด์นฉ๋‹ˆ๋‹ค!");
    }
}

โœ” Person์„ ์ƒ์†๋ฐ›์•„ ๊ณตํ†ต ์†์„ฑ(name, age) ์‚ฌ์šฉ

โœ” Teacher๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ teach() ๊ฐ•์ œ ๊ตฌํ˜„


7๏ธโƒฃ ์‹คํ–‰ํ•˜๊ธฐ (SchoolTest.java)

๐Ÿ’ก ์ด์ œ ํ•™์ƒ๊ณผ ์„ ์ƒ๋‹˜์„ ๋งŒ๋“ค๊ณ , ์ˆ™์ œ์™€ ์ˆ˜์—…์„ ์ง„ํ–‰ํ•ด๋ณผ๊ฒŒ์š”!

๐Ÿ“Œ SchoolTest.java (๋ฉ”์ธ ์‹คํ–‰ ํŒŒ์ผ)

package school;

public class SchoolTest {
    public static void main(String[] args) {
        Student student = new Student("์ฒ ์ˆ˜", 15);
        MathTeacher teacher = new MathTeacher("๊น€์„ ์ƒ๋‹˜", 40);

        student.showInfo();
        student.doHomework();

        teacher.showInfo();
        teacher.teach();
    }
}

โœ… ์‹คํ–‰ ๊ฒฐ๊ณผ:

๐Ÿ‘ค ์ด๋ฆ„: ์ฒ ์ˆ˜, ๋‚˜์ด: 15
๐Ÿ“š ์ฒ ์ˆ˜๊ฐ€(์ด) ์ˆ™์ œ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค!
๐Ÿ‘ค ์ด๋ฆ„: ๊น€์„ ์ƒ๋‹˜, ๋‚˜์ด: 40
๐Ÿ“– ๊น€์„ ์ƒ๋‹˜๊ฐ€(์ด) ์ˆ˜ํ•™์„ ๊ฐ€๋ฅด์นฉ๋‹ˆ๋‹ค!

๐ŸŽฏ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•˜๋Š” ์ด์œ 

โœ… ์œ ์—ฐํ•œ ์ฝ”๋“œ โ†’ ํด๋ž˜์Šค๊ฐ€ ํŠน์ • ๊ธฐ๋Šฅ์„ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•˜๋„๋ก ๊ฐ•์ œ

โœ… ๋‹ค์ค‘ ๊ตฌํ˜„ ๊ฐ€๋Šฅ โ†’ ํด๋ž˜์Šค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Œ

โœ… ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถค โ†’ ์ฝ”๋“œ ๋ณ€๊ฒฝ์ด ์‰ฌ์›Œ์ง€๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์šฉ์ด


๐ŸŽฏ ๊ธฐ์ˆ  ๋ฉด์ ‘์—์„œ ์ž์ฃผ ๋‚˜์˜ค๋Š” ์งˆ๋ฌธ๊ณผ ๋‹ต๋ณ€

Q1. ํด๋ž˜์Šค์™€ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ฐจ์ด๋Š”?

๊ฐœ๋… ํด๋ž˜์Šค ์ธํ„ฐํŽ˜์ด์Šค
๋ชฉ์  ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ์„ค๊ณ„๋„ ๊ทœ์น™์„ ์ •์˜ํ•˜๊ณ  ๊ฐ•์ œ
์ƒ์† ๋‹จ์ผ ์ƒ์†๋งŒ ๊ฐ€๋Šฅ (extends) ๋‹ค์ค‘ ๊ตฌํ˜„ ๊ฐ€๋Šฅ (implements)
๋‚ด์šฉ ์†์„ฑ๊ณผ ๋ฉ”์„œ๋“œ๋ฅผ ํฌํ•จ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฉ”์„œ๋“œ๋งŒ ํฌํ•จ
๊ฐ์ฒด ์ƒ์„ฑ new ํ‚ค์›Œ๋“œ๋กœ ๊ฐ์ฒด ์ƒ์„ฑ ๊ฐ€๋Šฅ ์ง์ ‘ ๊ฐ์ฒด ์ƒ์„ฑ ๋ถˆ๊ฐ€

Q2. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š”?

โœ… ์œ ์—ฐํ•œ ์ฝ”๋“œ โ†’ ํด๋ž˜์Šค๊ฐ€ ํŠน์ • ๊ธฐ๋Šฅ์„ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•˜๋„๋ก ๊ฐ•์ œ

โœ… ๋‹ค์ค‘ ๊ตฌํ˜„ ๊ฐ€๋Šฅ โ†’ ํด๋ž˜์Šค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Œ

โœ… ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถค โ†’ ์ฝ”๋“œ ๋ณ€๊ฒฝ์ด ์‰ฌ์›Œ์ง€๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์šฉ์ด


๐Ÿš€ ๋งˆ๋ฌด๋ฆฌ

โœ… ํŒจํ‚ค์ง€๋Š” ๊ด€๋ จ๋œ ํด๋ž˜์Šค๋“ค์„ ์ •๋ฆฌํ•˜๋Š” ํด๋”

โœ… ์ธํ„ฐํŽ˜์ด์Šค๋Š” โ€œ๋ฐ˜๋“œ์‹œ ํ•ด์•ผ ํ•˜๋Š” ๊ธฐ๋Šฅโ€์„ ์ •์˜ํ•˜๋Š” ๊ทœ์น™

โœ… ๋ถ€๋ชจ ํด๋ž˜์Šค๋Š” ๊ณตํ†ต ์†์„ฑ์„ ์ œ๊ณตํ•˜๊ณ  ์ฝ”๋“œ ์ค‘๋ณต์„ ์ค„์ž„

๐Ÿ“Œ 8๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค ์‹ฌํ™” ๊ฐœ๋…๊ณผ ์‹ค๋ฌด ํ™œ์šฉ ์™„๋ฒฝ ์ •๋ฆฌ!


8๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค(interface) - ๊ฐœ๋…๋ถ€ํ„ฐ ์ตœ์‹  ํŠธ๋ Œ๋“œ๊นŒ์ง€ ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ธฐ

๐Ÿ’ก ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํด๋ž˜์Šค๊ฐ€ ๋”ฐ๋ผ์•ผ ํ•˜๋Š” โ€œ๊ทœ์น™โ€์„ ์ •์˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ‘‰ โ€œ๋ฉ”๋‰ดํŒโ€๊ณผ ๋น„์Šทํ•˜๊ฒŒ, ์–ด๋–ค ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์•ผ ํ•˜๋Š”์ง€ ์„ ์–ธํ•˜์ง€๋งŒ, ์‹ค์ œ ๊ตฌํ˜„์€ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๐ŸŽฏ ์ธํ„ฐํŽ˜์ด์Šค์˜ ํ•ต์‹ฌ ๊ฐœ๋…

โœ… ํด๋ž˜์Šค๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ง€๋งŒ, ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†์Œ

โœ… ํด๋ž˜์Šค๋Š” extends๋กœ ์ƒ์†, ์ธํ„ฐํŽ˜์ด์Šค๋Š” implements๋กœ ๊ตฌํ˜„

โœ… ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋Š” public abstract๊ฐ€ ์ž๋™ ์ ์šฉ

โœ… ๋ชจ๋“  ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋Š” public static final (์ƒ์ˆ˜)๋กœ ์ž๋™ ์„ค์ •

โœ… JDK 8๋ถ€ํ„ฐ default, static ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€ (์ธํ„ฐํŽ˜์ด์Šค ๋‚ด ๊ตฌํ˜„ ๊ฐ€๋Šฅ)

โœ… JDK 9๋ถ€ํ„ฐ private ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€ (์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ ์ฆ๊ฐ€)


9๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌ์„ฑ ์š”์†Œ

(1) ์ƒ์ˆ˜ (Constant)

๐Ÿ“Œ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋ฉด ์ž๋™์œผ๋กœ public static final์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

interface MyInterface {
    int MAX_VALUE = 100;  // ์ž๋™์œผ๋กœ public static final ์ ์šฉ
}

(2) ์ถ”์ƒ ๋ฉ”์„œ๋“œ (Abstract Method)

๐Ÿ“Œ ์ธํ„ฐํŽ˜์ด์Šค์— ์„ ์–ธ๋œ ๋ฉ”์„œ๋“œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ถ”์ƒ ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค.

interface Animal {
    void makeSound();  // ์ž๋™์œผ๋กœ public abstract ์ ์šฉ๋จ
}

(3) ๋””ํดํŠธ ๋ฉ”์„œ๋“œ (Default Method) - JDK 8 ์ถ”๊ฐ€

๐Ÿ“Œ ๊ตฌํ˜„๋ถ€๊ฐ€ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์ง์ ‘ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Œ

interface Animal {
    default void sleep() {
        System.out.println("์ž ์„ ์žก๋‹ˆ๋‹ค.");
    }
}

(4) ์ •์  ๋ฉ”์„œ๋“œ (Static Method) - JDK 8 ์ถ”๊ฐ€

๐Ÿ“Œ ์ธํ„ฐํŽ˜์ด์Šค ์ž์ฒด์—์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ

interface MathUtil {
    static int add(int a, int b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(MathUtil.add(3, 5)); // ์ถœ๋ ฅ: 8
    }
}

(5) ํ”„๋ผ์ด๋น— ๋ฉ”์„œ๋“œ (Private Method) - JDK 9 ์ถ”๊ฐ€

๐Ÿ“Œ ์ธํ„ฐํŽ˜์ด์Šค ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ

interface NewFeature {
    private void helperMethod() {
        System.out.println("๋„์›€์ด ๋˜๋Š” ๊ธฐ๋Šฅ!");
    }

    default void showFeature() {
        helperMethod();
    }
}

โœ… ์ค‘๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ private ๋ฉ”์„œ๋“œ๋กœ ๋ฌถ์–ด ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Œ


๐Ÿ”Ÿ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„๊ณผ ๋‹คํ˜•์„ฑ(Polymorphism)

๐Ÿ’ก ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ

interface Animal {
    void makeSound();
}

class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("๋ฉ๋ฉ!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        myDog.makeSound(); // ์ถœ๋ ฅ: ๋ฉ๋ฉ!
    }
}

โœ… ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž๋ฃŒํ˜•์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

โœ… ๋‹คํ˜•์„ฑ์„ ํ™œ์šฉํ•˜๋ฉด ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋†’์•„์ง


1๏ธโƒฃ1๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋‹คํ˜•์„ฑ ํ™œ์šฉ (Polymorphism)

๐Ÿ“Œ ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž…์œผ๋กœ ์—ฌ๋Ÿฌ ๊ตฌํ˜„์ฒด๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Œ

interface Animal {
    void makeSound();
}

class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("๋ฉ๋ฉ!");
    }
}

class Cat implements Animal {
    @Override
    public void makeSound() {
        System.out.println("์•ผ์˜น!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myPet = new Dog(); // Animal ํƒ€์ž…์œผ๋กœ Dog ๊ฐ์ฒด ์ฐธ์กฐ
        myPet.makeSound(); // ์ถœ๋ ฅ: ๋ฉ๋ฉ!

        myPet = new Cat(); // Animal ํƒ€์ž…์œผ๋กœ Cat ๊ฐ์ฒด ์ฐธ์กฐ
        myPet.makeSound(); // ์ถœ๋ ฅ: ์•ผ์˜น!
    }
}

โœ… ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์ด ๊ฐ์ฒด๋ฅผ ์‰ฝ๊ฒŒ ๊ต์ฒด ๊ฐ€๋Šฅ

โœ… ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถฐ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋›ฐ์–ด๋‚จ


1๏ธโƒฃ2๏ธโƒฃ instanceof ์—ฐ์‚ฐ์ž (๊ฐ์ฒด ํƒ€์ž… ํ™•์ธ)

๐Ÿ“Œ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ฐธ์กฐ๋œ ๊ฐ์ฒด๊ฐ€ ์‹ค์ œ๋กœ ์–ด๋–ค ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ธ์ง€ ํ™•์ธํ•  ๋•Œ ์‚ฌ์šฉ

if (myPet instanceof Cat) {
    System.out.println("myPet์€ Cat ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ž…๋‹ˆ๋‹ค.");
}

1๏ธโƒฃ3๏ธโƒฃ ์ตœ์‹  ํŠธ๋ Œ๋“œ: JDK 9 ์ดํ›„ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ณ€ํ™”

๐Ÿ“Œ JDK 9๋ถ€ํ„ฐ private ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€๋กœ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ ์ฆ๊ฐ€

interface NewFeature {
    private void helperMethod() {
        System.out.println("๋„์›€์ด ๋˜๋Š” ๊ธฐ๋Šฅ!");
    }

    default void showFeature() {
        helperMethod();
    }
}

โœ… ์ค‘๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ private ๋ฉ”์„œ๋“œ๋กœ ๋ฌถ์–ด ๊ด€๋ฆฌ ๊ฐ€๋Šฅ


1๏ธโƒฃ4๏ธโƒฃ ์‹ค๋ฌด์—์„œ ์ธํ„ฐํŽ˜์ด์Šค ํ™œ์šฉ ์˜ˆ์‹œ

๐Ÿ’ก ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋›ฐ์–ด๋‚˜๊ณ  ํ™•์žฅ์„ฑ์ด ์ข‹์€ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ

๐Ÿ“Œ ๊ฒฐ์ œ ์‹œ์Šคํ…œ ์˜ˆ์ œ

interface Payment {
    void pay(int amount);
}

class KakaoPay implements Payment {
    @Override
    public void pay(int amount) {
        System.out.println("์นด์นด์˜คํŽ˜์ด๋กœ " + amount + "์› ๊ฒฐ์ œ");
    }
}

class NaverPay implements Payment {
    @Override
    public void pay(int amount) {
        System.out.println("๋„ค์ด๋ฒ„ํŽ˜์ด๋กœ " + amount + "์› ๊ฒฐ์ œ");
    }
}

public class Main {
    public static void main(String[] args) {
        Payment payment = new KakaoPay();  // ๊ฒฐ์ œ ์ˆ˜๋‹จ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
        payment.pay(5000);

        payment = new NaverPay();  // ๋„ค์ด๋ฒ„ํŽ˜์ด๋กœ ๋ณ€๊ฒฝ
        payment.pay(10000);
    }
}

โœ… ์ธํ„ฐํŽ˜์ด์Šค ๋•๋ถ„์— ๊ฒฐ์ œ ์ˆ˜๋‹จ์„ ์‰ฝ๊ฒŒ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ

โœ… ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ ๋„ ์ƒˆ๋กœ์šด ๊ฒฐ์ œ ๋ฐฉ์‹ ๋„์ž… ๊ฐ€๋Šฅ


๐ŸŽฏ ๋งˆ๋ฌด๋ฆฌ - ์ธํ„ฐํŽ˜์ด์Šค์˜ ํ•ต์‹ฌ ์š”์•ฝ!

โœ… ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํด๋ž˜์Šค๊ฐ€ ๋”ฐ๋ผ์•ผ ํ•˜๋Š” โ€œ์„ค๋ช…์„œโ€ ์—ญํ• 

โœ… ๊ฐ์ฒด ์ƒ์„ฑ ๋ถˆ๊ฐ€, ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ ํด๋ž˜์Šค์—์„œ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ

โœ… ๋‹ค์ค‘ ๊ตฌํ˜„ ๊ฐ€๋Šฅ โ†’ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ ๊ฐ€๋Šฅ

โœ… JDK 8 ์ดํ›„ default, static ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€

โœ… JDK 9 ์ดํ›„ private ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€๋กœ ์ฝ”๋“œ ์ค‘๋ณต ์ œ๊ฑฐ ๊ฐ€๋Šฅ

โœ… ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ณ  ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋›ฐ์–ด๋‚œ ์ฝ”๋“œ ์ž‘์„ฑ ๊ฐ€๋Šฅ


###


1๏ธโƒฃ5๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ณ ๊ธ‰ ํ™œ์šฉ: ๋””์ž์ธ ํŒจํ„ด ์ ์šฉ

์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋””์ž์ธ ํŒจํ„ด๊ณผ ๊ฒฐํ•ฉํ•˜์—ฌ ์œ ์—ฐํ•˜๊ณ  ํ™•์žฅ์„ฑ์ด ์ข‹์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋Œ€ํ‘œ์ ์œผ๋กœ ์ „๋žต ํŒจํ„ด(Strategy Pattern)๊ณผ ํŒฉํ† ๋ฆฌ ํŒจํ„ด(Factory Pattern)์ด ์žˆ์Šต๋‹ˆ๋‹ค.


๐ŸŽฏ ์ „๋žต ํŒจํ„ด(Strategy Pattern) - ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์œ ์—ฐํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•˜๊ธฐ

๐Ÿ’ก ์ „๋žต ํŒจํ„ด์€ ์‹คํ–‰ ์ค‘์— ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ•˜๋Š” ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

โœ… ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์‹คํ–‰ ์ค‘์—๋„ ์‰ฝ๊ฒŒ ์ „๋žต(๊ธฐ๋Šฅ)์„ ๊ต์ฒด ๊ฐ€๋Šฅ

๐Ÿ“Œ ์˜ˆ์ œ: ๋‹ค์–‘ํ•œ ์ •๋ ฌ ๋ฐฉ๋ฒ•์„ ์ง€์›ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ

// ์ •๋ ฌ ๋ฐฉ์‹ ์ธํ„ฐํŽ˜์ด์Šค
interface SortStrategy {
    void sort(int[] numbers);
}

// ๋ฒ„๋ธ” ์ •๋ ฌ ๊ตฌํ˜„
class BubbleSort implements SortStrategy {
    @Override
    public void sort(int[] numbers) {
        System.out.println("๋ฒ„๋ธ” ์ •๋ ฌ ์ˆ˜ํ–‰");
    }
}

// ํ€ต ์ •๋ ฌ ๊ตฌํ˜„
class QuickSort implements SortStrategy {
    @Override
    public void sort(int[] numbers) {
        System.out.println("ํ€ต ์ •๋ ฌ ์ˆ˜ํ–‰");
    }
}

// ์ •๋ ฌ์„ ์‹คํ–‰ํ•˜๋Š” ์ปจํ…์ŠคํŠธ ํด๋ž˜์Šค
class SortContext {
    private SortStrategy strategy;

    public void setStrategy(SortStrategy strategy) {
        this.strategy = strategy;
    }

    public void executeSort(int[] numbers) {
        strategy.sort(numbers);
    }
}

// ์‹คํ–‰ ์ฝ”๋“œ
public class Main {
    public static void main(String[] args) {
        SortContext context = new SortContext();

        context.setStrategy(new BubbleSort());
        context.executeSort(new int[]{5, 2, 9, 1});

        context.setStrategy(new QuickSort());
        context.executeSort(new int[]{5, 2, 9, 1});
    }
}

โœ… ์‹คํ–‰ ๊ฒฐ๊ณผ:

๋ฒ„๋ธ” ์ •๋ ฌ ์ˆ˜ํ–‰
ํ€ต ์ •๋ ฌ ์ˆ˜ํ–‰

๐Ÿ‘‰ ์‹คํ–‰ ์ค‘์— BubbleSort์—์„œ QuickSort๋กœ ์ „๋žต์„ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ!

๐Ÿ‘‰ ์ƒˆ๋กœ์šด ์ •๋ ฌ ๋ฐฉ์‹ ์ถ”๊ฐ€ ์‹œ SortStrategy ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ๊ตฌํ˜„ํ•˜๋ฉด ๋จ!


๐ŸŽฏ ํŒฉํ† ๋ฆฌ ํŒจํ„ด(Factory Pattern) - ๊ฐ์ฒด ์ƒ์„ฑ์„ ์œ ์—ฐํ•˜๊ฒŒ ๊ด€๋ฆฌํ•˜๊ธฐ

๐Ÿ’ก ํŒฉํ† ๋ฆฌ ํŒจํ„ด์€ ๊ฐ์ฒด ์ƒ์„ฑ์„ ์ค‘์•™์—์„œ ๊ด€๋ฆฌํ•˜์—ฌ ์œ ์—ฐ์„ฑ์„ ๋†’์ด๋Š” ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

โœ… ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹

๐Ÿ“Œ ์˜ˆ์ œ: ๊ฒฐ์ œ ์‹œ์Šคํ…œ์—์„œ ๊ฒฐ์ œ ์ˆ˜๋‹จ์„ ๋™์ ์œผ๋กœ ์„ ํƒ

// ๊ฒฐ์ œ ์ธํ„ฐํŽ˜์ด์Šค
interface Payment {
    void pay(int amount);
}

// ๊ฒฐ์ œ ๋ฐฉ์‹ ๊ตฌํ˜„
class KakaoPay implements Payment {
    @Override
    public void pay(int amount) {
        System.out.println("์นด์นด์˜คํŽ˜์ด๋กœ " + amount + "์› ๊ฒฐ์ œ");
    }
}

class NaverPay implements Payment {
    @Override
    public void pay(int amount) {
        System.out.println("๋„ค์ด๋ฒ„ํŽ˜์ด๋กœ " + amount + "์› ๊ฒฐ์ œ");
    }
}

// ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค (๊ฐ์ฒด ์ƒ์„ฑ ์ฑ…์ž„์„ ๊ฐ€์ง)
class PaymentFactory {
    public static Payment getPaymentMethod(String type) {
        if (type.equalsIgnoreCase("KakaoPay")) {
            return new KakaoPay();
        } else if (type.equalsIgnoreCase("NaverPay")) {
            return new NaverPay();
        }
        throw new IllegalArgumentException("์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฐ์ œ ์ˆ˜๋‹จ");
    }
}

// ์‹คํ–‰ ์ฝ”๋“œ
public class Main {
    public static void main(String[] args) {
        Payment payment = PaymentFactory.getPaymentMethod("KakaoPay");
        payment.pay(5000);

        payment = PaymentFactory.getPaymentMethod("NaverPay");
        payment.pay(10000);
    }
}

โœ… ์‹คํ–‰ ๊ฒฐ๊ณผ:

์นด์นด์˜คํŽ˜์ด๋กœ 5000์› ๊ฒฐ์ œ
๋„ค์ด๋ฒ„ํŽ˜์ด๋กœ 10000์› ๊ฒฐ์ œ

๐Ÿ‘‰ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์—์„œ๋Š” new ํ‚ค์›Œ๋“œ๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  PaymentFactory๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ!

๐Ÿ‘‰ ์ƒˆ๋กœ์šด ๊ฒฐ์ œ ๋ฐฉ์‹ ์ถ”๊ฐ€ ์‹œ Payment ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ํ™•์žฅ์ด ์‰ฌ์›€!


1๏ธโƒฃ6๏ธโƒฃ ์ตœ์‹  ํŠธ๋ Œ๋“œ - JDK 9 ์ดํ›„์˜ ์ธํ„ฐํŽ˜์ด์Šค ๋ณ€ํ™”

JDK 9 ์ดํ›„ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์—ญํ• ์ด ํ™•์žฅ๋˜๋ฉด์„œ ๋” ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ”น 1. ์ธํ„ฐํŽ˜์ด์Šค ๋‚ด private ๋ฉ”์„œ๋“œ ์ง€์› (JDK 9)

๐Ÿ’ก ์ด์ „์—๋Š” ์ธํ„ฐํŽ˜์ด์Šค์—์„œ default ๋ฉ”์„œ๋“œ ๋‚ด ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ์—†์• ๊ธฐ ์–ด๋ ค์› ์Œ

โœ… ์ด์ œ private ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์ฝ”๋“œ ์ค‘๋ณต์„ ์ค„์ผ ์ˆ˜ ์žˆ์Œ

interface Logger {
    private void log(String message) {
        System.out.println("[LOG]: " + message);
    }

    default void error(String message) {
        log("ERROR: " + message);
    }

    default void info(String message) {
        log("INFO: " + message);
    }
}

๐Ÿ‘‰ log() ๋ฉ”์„œ๋“œ๋ฅผ private์œผ๋กœ ์„ ์–ธํ•˜์—ฌ ๋‚ด๋ถ€์ ์œผ๋กœ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ!

๐Ÿ‘‰ error()์™€ info()์—์„œ ์ค‘๋ณต ์ฝ”๋“œ ์ œ๊ฑฐ ๊ฐ€๋Šฅ!


๐Ÿ”น 2. ์ธํ„ฐํŽ˜์ด์Šค ๋‚ด static ๋ฉ”์„œ๋“œ ํ™œ์šฉ (JDK 8)

๐Ÿ’ก ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•  ๋•Œ ์œ ์šฉ

โœ… ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

interface MathUtil {
    static int square(int x) {
        return x * x;
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(MathUtil.square(5)); // ์ถœ๋ ฅ: 25
    }
}

๐Ÿ‘‰ static ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค์ฒ˜๋Ÿผ ํ™œ์šฉ ๊ฐ€๋Šฅ!


1๏ธโƒฃ7๏ธโƒฃ ๊ธฐ์ˆ  ๋ฉด์ ‘์—์„œ ์ธํ„ฐํŽ˜์ด์Šค ํ™œ์šฉํ•˜๊ธฐ

๐ŸŽฏ ๋ฉด์ ‘ ์งˆ๋ฌธ 1: ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š”?

โœ… ์œ ์—ฐํ•œ ์ฝ”๋“œ โ†’ ์—ฌ๋Ÿฌ ํด๋ž˜์Šค๊ฐ€ ๊ฐ™์€ ๊ทœ์น™์„ ๋”ฐ๋ฅด๋„๋ก ๊ฐ•์ œ

โœ… ๋‹ค์ค‘ ๊ตฌํ˜„ ๊ฐ€๋Šฅ โ†’ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๊ฐ€ ์—ฌ๋Ÿฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ ๊ฐ€๋Šฅ

โœ… ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถค โ†’ ์ฝ”๋“œ ๋ณ€๊ฒฝ์ด ์‰ฌ์›Œ์ง€๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์šฉ์ด

๐ŸŽฏ ๋ฉด์ ‘ ์งˆ๋ฌธ 2: ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ถ”์ƒ ํด๋ž˜์Šค์˜ ์ฐจ์ด์ ์€?

๊ตฌ๋ถ„ ์ธํ„ฐํŽ˜์ด์Šค ์ถ”์ƒ ํด๋ž˜์Šค
๋ชฉ์  ๊ธฐ๋Šฅ์˜ โ€œ๊ทœ์•ฝโ€ ์ œ๊ณต ๊ณตํ†ต ์†์„ฑ & ๋ฉ”์„œ๋“œ ์ œ๊ณต
๊ฐ์ฒด ์ƒ์„ฑ ์ง์ ‘ ์ƒ์„ฑ ๋ถˆ๊ฐ€ ์ง์ ‘ ์ƒ์„ฑ ๋ถˆ๊ฐ€
์ƒ์† ๊ด€๊ณ„ ๋‹ค์ค‘ ๊ตฌํ˜„ ๊ฐ€๋Šฅ (implements) ๋‹จ์ผ ์ƒ์† (extends)
๊ตฌ์„ฑ ์š”์†Œ public abstract ๋ฉ”์„œ๋“œ, static & default ๋ฉ”์„œ๋“œ (JDK 8+) ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ, ํ•„๋“œ, abstract ๋ฉ”์„œ๋“œ

๐Ÿš€ ์ตœ์ข… ๋งˆ๋ฌด๋ฆฌ

โœ… ์ธํ„ฐํŽ˜์ด์Šค๋Š” OOP์—์„œ ๊ฐ•๋ ฅํ•œ ์„ค๊ณ„ ๋„๊ตฌ๋กœ ์‚ฌ์šฉ๋จ

โœ… ๋””์ž์ธ ํŒจํ„ด(์ „๋žต ํŒจํ„ด, ํŒฉํ† ๋ฆฌ ํŒจํ„ด)๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋†’์•„์ง

โœ… JDK 8+ ์ดํ›„ default, static ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€ โ†’ ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋Šฅ ํ™•์žฅ

โœ… JDK 9+ ์ดํ›„ private ๋ฉ”์„œ๋“œ ์ง€์› โ†’ ์ค‘๋ณต ์ฝ”๋“œ ์ œ๊ฑฐ ๊ฐ€๋Šฅ

โœ… ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์‹ค๋ฌด์—์„œ ๋” ์œ ์—ฐํ•˜๊ณ  ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์‹œ์Šคํ…œ์„ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์Œ


๐ŸŽฏ ์ด์ œ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชจ๋“  ๊ฐœ๋…์„ ๋งˆ์Šคํ„ฐํ–ˆ์–ด์š”! ๐ŸŽฏ

๐Ÿ‘‰ ์ด์ œ ์‹ค๋ฌด์—์„œ๋„ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž์œ ๋กญ๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ๋ฉด์ ‘์—์„œ๋„ ์™„๋ฒฝํžˆ ๋Œ€๋‹ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค! ๐Ÿš€

1๏ธโƒฃ8๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค์™€ SOLID ์›์น™

๐Ÿ’ก ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(OOP)์˜ ์ค‘์š”ํ•œ ์›์น™์ธ SOLID ์›์น™์„ ๋”ฐ๋ฅด๋Š” ๋ฐ ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

โœ… S (๋‹จ์ผ ์ฑ…์ž„ ์›์น™, SRP)

โœ… O (๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™, OCP)

โœ… L (๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™, LSP)

โœ… I (์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™, ISP)

โœ… D (์˜์กด ์—ญ์ „ ์›์น™, DIP)

๐Ÿ“Œ ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™(ISP) ์˜ˆ์ œ

// ์ž˜๋ชป๋œ ์˜ˆ์‹œ: ํ•˜๋‚˜์˜ ์ธํ„ฐํŽ˜์ด์Šค์— ๋„ˆ๋ฌด ๋งŽ์€ ๊ธฐ๋Šฅ ํฌํ•จ
interface Worker {
    void work();
    void eat();
}

class HumanWorker implements Worker {
    @Override
    public void work() {
        System.out.println("์‚ฌ๋žŒ์ด ์ผํ•จ");
    }

    @Override
    public void eat() {
        System.out.println("์‚ฌ๋žŒ์ด ๋ฐฅ์„ ๋จน์Œ");
    }
}

class RobotWorker implements Worker {
    @Override
    public void work() {
        System.out.println("๋กœ๋ด‡์ด ์ผํ•จ");
    }

    @Override
    public void eat() {
        // ๋กœ๋ด‡์€ ๋จน์ง€ ์•Š์Œ! ํ•˜์ง€๋งŒ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ
        throw new UnsupportedOperationException("๋กœ๋ด‡์€ ๋จน์ง€ ์•Š์Œ");
    }
}

๐Ÿ‘Ž ๋ฌธ์ œ์ :

๐Ÿ“Œ ISP๋ฅผ ์ ์šฉํ•œ ๊ฐœ์„ ๋œ ์ฝ”๋“œ

interface Workable {
    void work();
}

interface Eatable {
    void eat();
}

class HumanWorker implements Workable, Eatable {
    @Override
    public void work() {
        System.out.println("์‚ฌ๋žŒ์ด ์ผํ•จ");
    }

    @Override
    public void eat() {
        System.out.println("์‚ฌ๋žŒ์ด ๋ฐฅ์„ ๋จน์Œ");
    }
}

class RobotWorker implements Workable {
    @Override
    public void work() {
        System.out.println("๋กœ๋ด‡์ด ์ผํ•จ");
    }
}

โœ… ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ธฐ๋Šฅ๋ณ„๋กœ ๋‚˜๋ˆ„์–ด ๋กœ๋ด‡์ด ํ•„์š”ํ•˜์ง€ ์•Š์€ ๊ธฐ๋Šฅ์„ ๊ฐ•์ œ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•„๋„ ๋จ!


1๏ธโƒฃ9๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋ฆฌํ”Œ๋ ‰์…˜(Reflection)

๐Ÿ’ก ์ž๋ฐ” ๋ฆฌํ”Œ๋ ‰์…˜(Reflection)์„ ํ™œ์šฉํ•˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋™์ ์œผ๋กœ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Œ.

โœ… ํด๋ž˜์Šค๊ฐ€ ์–ด๋–ค ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š”์ง€ ํ™•์ธ ๊ฐ€๋Šฅ

โœ… ๋™์ ์œผ๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Œ

๐Ÿ“Œ ๋ฆฌํ”Œ๋ ‰์…˜์„ ์‚ฌ์šฉํ•ด ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ ์—ฌ๋ถ€ ํ™•์ธํ•˜๊ธฐ

import java.lang.reflect.Method;

interface Animal {
    void makeSound();
}

class Dog implements Animal {
    @Override
    public void makeSound() {
        System.out.println("๋ฉ๋ฉ!");
    }
}

public class ReflectionExample {
    public static void main(String[] args) {
        Class<?> clazz = Dog.class;

        // ํŠน์ • ํด๋ž˜์Šค๊ฐ€ ํŠน์ • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ–ˆ๋Š”์ง€ ํ™•์ธ
        boolean isAnimal = Animal.class.isAssignableFrom(clazz);
        System.out.println("Dog ํด๋ž˜์Šค๊ฐ€ Animal ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ–ˆ๋Š”๊ฐ€? " + isAnimal);

        // ๋ฉ”์„œ๋“œ ๋ชฉ๋ก ์ถœ๋ ฅ
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println("๋ฉ”์„œ๋“œ: " + method.getName());
        }
    }
}

โœ… ์ถœ๋ ฅ ๊ฒฐ๊ณผ:

Dog ํด๋ž˜์Šค๊ฐ€ Animal ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ–ˆ๋Š”๊ฐ€? true
๋ฉ”์„œ๋“œ: makeSound

๐Ÿ‘‰ ๋ฆฌํ”Œ๋ ‰์…˜์„ ํ™œ์šฉํ•˜๋ฉด ๋Ÿฐํƒ€์ž„ ์‹œ ์ธํ„ฐํŽ˜์ด์Šค ์ •๋ณด๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Œ!


2๏ธโƒฃ0๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋žŒ๋‹ค(Lambda) ํ™œ์šฉ

๐Ÿ’ก ์ž๋ฐ” 8๋ถ€ํ„ฐ ๋“ฑ์žฅํ•œ ๋žŒ๋‹ค ํ‘œํ˜„์‹์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋” ํšจ์œจ์ ์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

โœ… ๋žŒ๋‹ค๋Š” ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋‹จ์ผ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ๋•Œ ์œ ์šฉํ•จ.

โœ… ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค(Functional Interface)์™€ ๊ฒฐํ•ฉํ•˜๋ฉด ๋งค์šฐ ๊ฐ•๋ ฅํ•จ.

๐Ÿ“Œ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ์˜ˆ์ œ (@FunctionalInterface ์‚ฌ์šฉ)

@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);
}

public class LambdaExample {
    public static void main(String[] args) {
        // ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„
        Calculator add = (a, b) -> a + b;
        Calculator multiply = (a, b) -> a * b;

        System.out.println("๋”ํ•˜๊ธฐ ๊ฒฐ๊ณผ: " + add.calculate(5, 3));  // 8
        System.out.println("๊ณฑํ•˜๊ธฐ ๊ฒฐ๊ณผ: " + multiply.calculate(5, 3));  // 15
    }
}

โœ… ์ถœ๋ ฅ ๊ฒฐ๊ณผ:

๋”ํ•˜๊ธฐ ๊ฒฐ๊ณผ: 8
๊ณฑํ•˜๊ธฐ ๊ฒฐ๊ณผ: 15

๐Ÿ‘‰ ๊ธฐ์กด ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„๋ณด๋‹ค ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋›ฐ์–ด๋‚จ!


2๏ธโƒฃ1๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜ API ์„ค๊ณ„

๐Ÿ’ก ์ž๋ฐ”์˜ ๋งŽ์€ API๋Š” ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜์œผ๋กœ ์„ค๊ณ„๋˜์–ด ์žˆ์Œ.

โœ… ์ž๋ฐ” ์ปฌ๋ ‰์…˜ ํ”„๋ ˆ์ž„์›Œํฌ (List, Set, Map) โ†’ ์ธํ„ฐํŽ˜์ด์Šค ์ค‘์‹ฌ ์„ค๊ณ„

โœ… ์ŠคํŠธ๋ฆผ API โ†’ Stream ์ธํ„ฐํŽ˜์ด์Šค ํ™œ์šฉ

๐Ÿ“Œ List ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•œ ์œ ์—ฐํ•œ ์„ค๊ณ„

import java.util.*;

public class InterfaceBasedAPI {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("์ฒ ์ˆ˜");
        names.add("์˜ํฌ");

        processList(names);
    }

    public static void processList(List<String> list) {
        for (String item : list) {
            System.out.println(item);
        }
    }
}

โœ… processList() ๋ฉ”์„œ๋“œ๋Š” List<String> ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ๋ฆฌ์ŠคํŠธ ๊ตฌํ˜„์ฒด(ArrayList, LinkedList)์™€ ํ˜ธํ™˜ ๊ฐ€๋Šฅ


๐Ÿš€ ๋งˆ๋ฌด๋ฆฌ: ์ธํ„ฐํŽ˜์ด์Šค ํ™œ์šฉ ์™„์ „ ์ •๋ณต!

โœ… ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ๋†’์ด๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ

โœ… SOLID ์›์น™์„ ๋”ฐ๋ฅด๋Š” ์„ค๊ณ„์— ํ•„์ˆ˜์ ์ธ ์š”์†Œ

โœ… ๋””์ž์ธ ํŒจํ„ด(์ „๋žต ํŒจํ„ด, ํŒฉํ† ๋ฆฌ ํŒจํ„ด)๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด ๊ฐ•๋ ฅํ•œ ์ฝ”๋“œ ๊ตฌ์กฐ ๊ตฌํ˜„ ๊ฐ€๋Šฅ

โœ… ๋ฆฌํ”Œ๋ ‰์…˜์„ ํ™œ์šฉํ•˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋™์  ๋ถ„์„ ๋ฐ ํ™œ์šฉ ๊ฐ€๋Šฅ

โœ… ๋žŒ๋‹ค์™€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๊ฐ„๊ฒฐํ•œ ์ฝ”๋“œ ์ž‘์„ฑ ๊ฐ€๋Šฅ

โœ… ์ž๋ฐ” API๋Š” ๋Œ€๋ถ€๋ถ„ ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜์œผ๋กœ ์„ค๊ณ„๋จ โ†’ ์‹ค๋ฌด์—์„œ ํ•„์ˆ˜์ ์ธ ๊ฐœ๋…


###


2๏ธโƒฃ2๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋‹จ์ ๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๐Ÿ’ก ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ด์ง€๋งŒ, ๋ช‡ ๊ฐ€์ง€ ๋‹จ์ ๋„ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ‘‰ ๋‹จ์ ์„ ๋ช…ํ™•ํžˆ ์ดํ•ดํ•˜๊ณ  ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ ์šฉํ•˜๋ฉด ๋”์šฑ ํšจ๊ณผ์ ์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ”น ๋‹จ์  1: ์ธํ„ฐํŽ˜์ด์Šค ๋‚จ์šฉ์œผ๋กœ ์ธํ•œ ๋ณต์žก์„ฑ ์ฆ๊ฐ€

โœ… ๋ฌธ์ œ์ 

โœ… ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๐Ÿ“Œ ๋ถˆํ•„์š”ํ•œ ์ธํ„ฐํŽ˜์ด์Šค ์„ค๊ณ„ ์˜ˆ์ œ (์ž˜๋ชป๋œ ์„ค๊ณ„)

interface Writeable {
    void write();
}

interface Readable {
    void read();
}

class FileManager implements Writeable, Readable {
    @Override
    public void write() {
        System.out.println("ํŒŒ์ผ ์ €์žฅ");
    }

    @Override
    public void read() {
        System.out.println("ํŒŒ์ผ ์ฝ๊ธฐ");
    }
}

๐Ÿ‘Ž ๋ฌธ์ œ์ : Writeable๊ณผ Readable ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ง€๋‚˜์น˜๊ฒŒ ์„ธ๋ถ„ํ™”๋จ.

๐Ÿ“Œ ๊ฐœ์„ ๋œ ์ฝ”๋“œ (์ธํ„ฐํŽ˜์ด์Šค ํ†ตํ•ฉ)

interface FileOperations {
    void read();
    void write();
}

class FileManager implements FileOperations {
    @Override
    public void write() {
        System.out.println("ํŒŒ์ผ ์ €์žฅ");
    }

    @Override
    public void read() {
        System.out.println("ํŒŒ์ผ ์ฝ๊ธฐ");
    }
}

โœ… ๋ถˆํ•„์š”ํ•œ ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ๋ฅผ ์ค„์ด๊ณ , ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ด!


๐Ÿ”น ๋‹จ์  2: ์ธํ„ฐํŽ˜์ด์Šค ๋ณ€๊ฒฝ์ด ์–ด๋ ค์›€

โœ… ๋ฌธ์ œ์ 

โœ… ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๐Ÿ“Œ ๊ธฐ์กด ๋ฐฉ์‹ (๋ณ€๊ฒฝ์ด ์–ด๋ ค์šด ์˜ˆ์ œ)

interface Printer {
    void print();
}

โœ… ์—ฌ๊ธฐ์— scan() ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ชจ๋“  ๊ตฌํ˜„์ฒด๊ฐ€ ์˜ํ–ฅ์„ ๋ฐ›์Œ

๐Ÿ“Œ JDK 8+์—์„œ default ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

interface Printer {
    void print();

    default void scan() {
        System.out.println("์Šค์บ” ๊ธฐ๋Šฅ ๊ธฐ๋ณธ ์ œ๊ณต");
    }
}

class InkjetPrinter implements Printer {
    @Override
    public void print() {
        System.out.println("์ž‰ํฌ์ ฏ ํ”„๋ฆฐํ„ฐ ์ถœ๋ ฅ");
    }
}

public class Main {
    public static void main(String[] args) {
        Printer printer = new InkjetPrinter();
        printer.print();
        printer.scan(); // ๊ธฐ์กด ๊ตฌํ˜„์ฒด์—์„œ๋„ scan() ์‚ฌ์šฉ ๊ฐ€๋Šฅ!
    }
}

โœ… ๊ธฐ์กด ๊ตฌํ˜„์ฒด ์ˆ˜์ • ์—†์ด ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ!


2๏ธโƒฃ3๏ธโƒฃ ์ธํ„ฐํŽ˜์ด์Šค ์„ฑ๋Šฅ ์ตœ์ ํ™” ์ „๋žต

๐Ÿ’ก ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„์˜ ์œ ์—ฐ์„ฑ์„ ๋†’์ด์ง€๋งŒ, ์„ฑ๋Šฅ ์ตœ์ ํ™”๋„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”น 1. ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ง์ ‘ ๊ตฌํ˜„ ํด๋ž˜์Šค์˜ ์„ฑ๋Šฅ ์ฐจ์ด

๐Ÿ“Œ ์˜ˆ์ œ: ์ธํ„ฐํŽ˜์ด์Šค vs ์ง์ ‘ ๊ตฌํ˜„ ํด๋ž˜์Šค ์„ฑ๋Šฅ ๋น„๊ต

interface Worker {
    void doWork();
}

class DirectWorker {
    void doWork() {
        System.out.println("์ง์ ‘ ํ˜ธ์ถœ");
    }
}

class InterfaceWorker implements Worker {
    @Override
    public void doWork() {
        System.out.println("์ธํ„ฐํŽ˜์ด์Šค ํ˜ธ์ถœ");
    }
}

public class PerformanceTest {
    public static void main(String[] args) {
        DirectWorker directWorker = new DirectWorker();
        Worker interfaceWorker = new InterfaceWorker(); // ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž… ์‚ฌ์šฉ

        long startTime = System.nanoTime();
        directWorker.doWork();
        long endTime = System.nanoTime();
        System.out.println("ํด๋ž˜์Šค ์ง์ ‘ ํ˜ธ์ถœ ์‹œ๊ฐ„: " + (endTime - startTime));

        startTime = System.nanoTime();
        interfaceWorker.doWork();
        endTime = System.nanoTime();
        System.out.println("์ธํ„ฐํŽ˜์ด์Šค ํ˜ธ์ถœ ์‹œ๊ฐ„: " + (endTime - startTime));
    }
}

โœ… ์ผ๋ฐ˜์ ์œผ๋กœ ํด๋ž˜์Šค ์ง์ ‘ ํ˜ธ์ถœ์ด ๋” ๋น ๋ฆ„ (ํ•˜์ง€๋งŒ ์ฐจ์ด๋Š” ๋ฏธ๋ฏธํ•จ)

โœ… ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•:


๐Ÿ”น 2. ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜์˜ ํŒฉํ† ๋ฆฌ ํŒจํ„ด ์ตœ์ ํ™”

๐Ÿ’ก ํŒฉํ† ๋ฆฌ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด ์ƒ์„ฑ์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์„ฑ๋Šฅ ์ตœ์ ํ™”๋„ ๊ณ ๋ คํ•ด์•ผ ํ•จ

โœ… ๋ฌธ์ œ์ : ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ

โœ… ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•: ์บ์‹ฑ์„ ํ™œ์šฉํ•˜์—ฌ ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉ (์‹ฑ๊ธ€ํ„ด ์ ์šฉ ๊ฐ€๋Šฅ)

๐Ÿ“Œ ์ตœ์ ํ™”๋œ ํŒฉํ† ๋ฆฌ ํŒจํ„ด (์‹ฑ๊ธ€ํ„ด ์ ์šฉ)

import java.util.HashMap;
import java.util.Map;

interface Payment {
    void pay(int amount);
}

class KakaoPay implements Payment {
    @Override
    public void pay(int amount) {
        System.out.println("์นด์นด์˜คํŽ˜์ด๋กœ " + amount + "์› ๊ฒฐ์ œ");
    }
}

class NaverPay implements Payment {
    @Override
    public void pay(int amount) {
        System.out.println("๋„ค์ด๋ฒ„ํŽ˜์ด๋กœ " + amount + "์› ๊ฒฐ์ œ");
    }
}

// ํŒฉํ† ๋ฆฌ ํŒจํ„ด + ์‹ฑ๊ธ€ํ„ด ์ ์šฉ (์บ์‹ฑ ํ™œ์šฉ)
class PaymentFactory {
    private static final Map<String, Payment> paymentCache = new HashMap<>();

    public static Payment getPaymentMethod(String type) {
        return paymentCache.computeIfAbsent(type, key -> {
            if (key.equalsIgnoreCase("KakaoPay")) return new KakaoPay();
            else if (key.equalsIgnoreCase("NaverPay")) return new NaverPay();
            throw new IllegalArgumentException("์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฐ์ œ ์ˆ˜๋‹จ");
        });
    }
}

public class Main {
    public static void main(String[] args) {
        Payment p1 = PaymentFactory.getPaymentMethod("KakaoPay");
        Payment p2 = PaymentFactory.getPaymentMethod("KakaoPay");

        System.out.println(p1 == p2); // true (๊ฐ™์€ ๊ฐ์ฒด ์‚ฌ์šฉ)
    }
}

โœ… ๊ฐ์ฒด๋ฅผ ์บ์‹ฑํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ ์ตœ์ ํ™”!

โœ… ๊ฐ์ฒด ์ƒ์„ฑ์„ ์ตœ์†Œํ™”ํ•˜์—ฌ ์„ฑ๋Šฅ ํ–ฅ์ƒ!


๐Ÿš€ ๋งˆ๋ฌด๋ฆฌ: ์ธํ„ฐํŽ˜์ด์Šค ๊ณ ๊ธ‰ ํ™œ์šฉ ์™„์ „ ์ •๋ณต!

โœ… ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„์˜ ํ•ต์‹ฌ ์š”์†Œ์ด์ง€๋งŒ, ๋‚จ์šฉํ•˜๋ฉด ๋ณต์žก์„ฑ์ด ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์Œ

โœ… JDK 8+ default ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ํ–ฅ์ƒ๋จ

โœ… ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ๊ณ ๋ คํ•ด์•ผ ํ•˜๋ฉฐ, ์บ์‹ฑ์„ ํ™œ์šฉํ•˜๋ฉด ํšจ์œจ์ ์ธ ์ธํ„ฐํŽ˜์ด์Šค ์„ค๊ณ„ ๊ฐ€๋Šฅ