** ๐ 0๋จ๊ณ ํต์ฌ ์์ฝ: ์ธํฐํ์ด์ค ์๋ฒฝ ์ ๋ฆฌ! **
โ ์ธํฐํ์ด์ค๋?
- ๊ธฐ๋ฅ์ ์ฝ์ํ๋ ๊ท์น
- ํด๋์ค๊ฐ ๋ฐ๋ผ์ผ ํ๋ โ์ค๋ช ์โ ์ญํ
โ ํด๋์ค์ ์ฐจ์ด์
- ํด๋์ค๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์์ง๋ง, ์ธํฐํ์ด์ค๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์์
- ํด๋์ค๋ ์์(extends), ์ธํฐํ์ด์ค๋ ๊ตฌํ(implements)
โ ์ธํฐํ์ด์ค์ ์ฃผ์ ํน์ง
- ๋ชจ๋ ๋ฉ์๋๋ public abstract (๊ตฌํ X)
- ๋ชจ๋ ๋ณ์๋ public static final (์์)
- ๋ค์ค ๊ตฌํ ๊ฐ๋ฅ (์ฌ๋ฌ ๊ฐ ์ธํฐํ์ด์ค ๊ตฌํ ๊ฐ๋ฅ)
- JDK 8 ์ด์:
default
&static
๋ฉ์๋ ์ถ๊ฐ - JDK 9 ์ด์:
private
๋ฉ์๋ ๊ฐ๋ฅ
โ ์ธํฐํ์ด์ค์ ํ์ฉ
- ์ ์ง๋ณด์์ฑ & ํ์ฅ์ฑ ํฅ์
- ๋คํ์ฑ(polymorphism) ์ง์
- ๊ฒฐํฉ๋๋ฅผ ๋ฎ์ถฐ ์ ์ฐํ ์ค๊ณ ๊ฐ๋ฅ
โ ์ค๋ฌด์์์ ์์
- ๊ฒฐ์ ์์คํ
:
Payment
์ธํฐํ์ด์ค โKakaoPay
,NaverPay
๊ตฌํ - ๊ฒ์ ๊ฐ๋ฐ:
Movable
์ธํฐํ์ด์ค โPlayer
,Enemy
๊ตฌํ
๐ ๊ฒฐ๋ก : ์ธํฐํ์ด์ค๋ ๊ฐ๋ ฅํ ์ค๊ณ ๋๊ตฌ๋ก, ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ(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("๋ก๋ด์ ๋จน์ง ์์");
}
}
๐ ๋ฌธ์ ์ :
- ๋ก๋ด์
eat()
๋ฉ์๋๋ฅผ ํ์๋ก ํ์ง ์์ง๋ง,Worker
์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด์ผ ํ๋ฏ๋ก ์์ธ ์ฒ๋ฆฌ๊ฐ ํ์ํจ.
๐ 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: ์ธํฐํ์ด์ค ๋จ์ฉ์ผ๋ก ์ธํ ๋ณต์ก์ฑ ์ฆ๊ฐ
โ ๋ฌธ์ ์
- ๋๋ฌด ์ธ๋ฐํ๊ฒ ์ธํฐํ์ด์ค๋ฅผ ๋ถ๋ฆฌํ๋ฉด ํด๋์ค๊ฐ ๋๋ฌด ๋ง์์ ธ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง ์ ์์
- ๋ถํ์ํ ์ธํฐํ์ด์ค ์ค๊ณ๋ ์ค๋ฒ ์์ง๋์ด๋ง(over-engineering)์ผ๋ก ์ด์ด์ง ์ ์์
โ ํด๊ฒฐ ๋ฐฉ๋ฒ
- SRP(๋จ์ผ ์ฑ ์ ์์น)์ ๋ง๊ฒ ์ค๊ณํ๋, ๋ถํ์ํ ๋ถ๋ฆฌ๋ฅผ ํผํจ
- ๊ธฐ๋ฅ์ด ๋๋ฌด ๋จ์ํ ๊ฒฝ์ฐ ์ธํฐํ์ด์ค ๋์ ์ถ์ ํด๋์ค๋ฅผ ํ์ฉ
- ๊ธฐ๋ณธ ๊ตฌํ์ด ํ์ํ ๊ฒฝ์ฐ JDK 8+์
default
๋ฉ์๋ ํ์ฉ
๐ ๋ถํ์ํ ์ธํฐํ์ด์ค ์ค๊ณ ์์ (์๋ชป๋ ์ค๊ณ)
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: ์ธํฐํ์ด์ค ๋ณ๊ฒฝ์ด ์ด๋ ค์
โ ๋ฌธ์ ์
- ๊ธฐ์กด ์ธํฐํ์ด์ค์ ์๋ก์ด ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ฉด, ๊ธฐ์กด ๊ตฌํ์ฒด๋ค์ด ๋ชจ๋ ์์ ๋์ด์ผ ํ๋ ๋ฌธ์ ๋ฐ์
- ๋ค์์ ํด๋์ค๊ฐ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ ์๋ค๋ฉด, ๋ณ๊ฒฝ์ด ๋งค์ฐ ์ด๋ ค์
โ ํด๊ฒฐ ๋ฐฉ๋ฒ
- JDK 8+์์ ์ถ๊ฐ๋
default
๋ฉ์๋ ์ฌ์ฉ - ๊ธฐ์กด ์ธํฐํ์ด์ค์ ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ฉด์๋, ๊ธฐ์กด ๊ตฌํ์ฒด์ ์ํฅ์ ์ฃผ์ง ์๋๋ก ํจ
๐ ๊ธฐ์กด ๋ฐฉ์ (๋ณ๊ฒฝ์ด ์ด๋ ค์ด ์์ )
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. ์ธํฐํ์ด์ค์ ์ง์ ๊ตฌํ ํด๋์ค์ ์ฑ๋ฅ ์ฐจ์ด
- ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ฉด JVM์ ๋ค์ด๋๋ฏน ๋์คํจ์น(dynamic dispatch, ๋์ ๋ฐ์ธ๋ฉ)๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค.
- ๋ฐ๋ฉด, ํด๋์ค๋ฅผ ์ง์ ์ฐธ์กฐํ๋ฉด ์ ์ ๋ฐ์ธ๋ฉ(static binding)์ด ๊ฐ๋ฅํ์ฌ ์ฑ๋ฅ์ด ๋ ๋น ๋ฅผ ์ ์์.
๐ ์์ : ์ธํฐํ์ด์ค 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
๋ฉ์๋๋ฅผ ํ์ฉํ๋ฉด ์ ์ง๋ณด์์ฑ์ด ํฅ์๋จ
โ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ๊ณ ๋ คํด์ผ ํ๋ฉฐ, ์บ์ฑ์ ํ์ฉํ๋ฉด ํจ์จ์ ์ธ ์ธํฐํ์ด์ค ์ค๊ณ ๊ฐ๋ฅ