[Java] ๊ธฐ์กด ์ธํฐํ์ด์ค์ ์๋ก์ด ๊ท์น์ ์ถ๊ฐํด๋ณด์!(์ถ์ํด๋์ค, ์ธํฐํ์ด์ค ์์)
ํ๊ทธ: Java, Refactoring
์นดํ ๊ณ ๋ฆฌ: Java
- ์ธํฐํ์ด์ค ๊ฐ์ ์์์ ๋ํด ์์๋ณธ๋ค.
- ์ถ์ํด๋์ค์ ํจ๊ป ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ ์ด์ ์ ์์๋ณธ๋ค.
์ธํฐํ์ด์ค ์์
๋ง์ฝ ์ด๋ฏธ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํด๋์ค๊ฐ ์ฌ๋ฟ ์กด์ฌํ๋ ์ํ์์ ์๋ก์ด ๊ท์น์ ์ธํฐํ์ด์ค์ ์ ์ํ๊ณ ์ถ์๋ ์ด๋ป๊ฒ ํด์ผํ ๊น? ์ด ๊ธ์์๋ ๊ธฐ์กด ์ธํฐํ์ด์ค์ ์๋ก์ด ๊ท์น ์ถ๊ฐ์ ๋ฐ์ํ๋ ๋๋ ๋ง๋ฅผ ํด๊ฒฐํ๋ ๊ณผ์ ์ ๋ํด ์ค๋ช ํ๋ค.
1
2
3
4
// Interface
public interface Spec {
void m1();
}
1
2
3
4
5
6
7
8
// Concrete Class
public class A implements Spec {
@Override
public void m1() {
System.out.println("A.m1()");
}
}
1
2
3
4
5
6
7
8
// Concrete Class
public class B implements Spec {
@Override
public void m1() {
System.out.println("B.m1()");
}
}
ํ์ฌ ์ด๋ฐ์์ผ๋ก ๊ตฌํ๋ ์ํ์ธ๋ฐ ์๋ก์ด ํด๋์ค C
๋ m1()
๊ธฐ๋ฅ์ธ์ ์๋ก์ด ๊ธฐ๋ฅ์ ์ ์ํด์ ์ฐ๊ณ ์ถ์ ์ํฉ์ด๋ค.
1
2
3
4
5
6
7
8
9
10
11
public class C implements Spec {
@Override
public void m1() {
System.out.println("A.m1()");
}
// ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ
public void m2() {
...
}
}
์ธํฐํ์ด์ค๋ ์ผ์ข
์ ๊ท์น ๋ชจ์์ด๊ธฐ ๋๋ฌธ์ ์ ์๋ ๊ท์น์ ๋ชจ๋ ๊ตฌํํด๋์ค๊ฐ ๋ฐ๋ผ์ผ๋ง ํ๋ค.
๋ง์ฝ m2()
๋ฅผ Spec
์ธํฐํ์ด์ค์ ์ถ์๋ฉ์๋๋ก ์ ์ํ๋ค๋ฉด Spec
์ ๊ตฌํํ ๋ชจ๋ ํด๋์ค์์ ์ฌ์ ์ํด์ผ ํ๋ค.
์๋ก์ด ๊ธฐ๋ฅ์ ์ธํฐํ์ด์ค์ ์ ์ํ๋ฉด์๋ ๊ธฐ์กด ๊ตฌํํด๋์ค์๋ ์ค๋ฅ์ ํ๊ฐ ๋์ง ์๋๋ก ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น?
์๋ฐ์์๋ ์ด๋ฌํ ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ
์ ์ ์ํ๋ค.
default method
java 8 ์ดํ๋ก ์ธํฐํ์ด์ค์์ default method
๋ฅผ ์์ฑํ ์ ์๋ค.
- ๊ธฐ์กด ํ๋ก์ ํธ์ ์ํฅ์ ๋ผ์น์ง ์์ผ๋ฉด์ ๊ธฐ์กด ๊ท์น์ ์ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ ๋ ์ ์ฉํ๋ค.
- ์ธํฐํ์ด์ค์์ ๋ฏธ๋ฆฌ ๊ตฌํํ ๋ฉ์๋์ด๊ธฐ ๋๋ฌธ์ ํด๋์ค์์ ๊ตฌํ์ ์๋ตํ ์ ์๋ค.
- ์๋ธํด๋์ค์ ๊ตฌํ์ ๊ฐ์ ํ ์ ์๋ค๋ ๊ฒ์ด ๋จ์ ์ด๋ค.
1
2
3
4
5
6
public implements Spec {
void m1();
// default method : ์๋ธํด๋์ค์์ ์ฌ์ ์ ํ ๋ฉ์๋์ด๊ธฐ ๋๋ฌธ์ ๋น ์ํ๋ก ๊ตฌํ๋ง ํด๋๋ค.
default void m2() {}
}
์์ default
ํค์๋๋ฅผ ๋ฃ๊ณ ๊ตฌํ๋ถ๊น์ง ์์ฑํด ์ฃผ๋ฉด ๋๋ค.
์ด๋ default
๋ ์ ๊ทผ์ ํ์์ default ๊ฐ ์๋๋ผ ์ธํฐํ์ด์ค์ ๋ํดํธ ๋ฉ์๋๋ฅผ ๋ปํ๋ค. (์ธํฐํ์ด์ค๋ ํญ์ ์ถ์๋ฉ์๋(public abstract
) ๋ง ๊ฐ์ง ์ ์๋ค..)
1
2
3
4
5
6
7
8
9
10
11
12
public class C implements Spec {
@Override
public void m1() {
System.out.println("A.m1()");
}
// ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ. ์ด ๋ฉ์๋๋ ์ถ์๋ฉ์๋๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ๊ตฌํ์ ๊ฐ์ ํ์ง ์๋๋ค.
@Override
public void m2() {
...
}
}
default method
๊ฐ ํ์ํ ๊ตฌํํด๋์ค์์ ํ์์ ๋ฐ๋ผ ๋ฉ์๋๋ฅผ ์ฌ์ ์ํด์ ์ฌ์ฉํ๋ฉด ๋๋ค.
๊ทธ๋ฌ๋ default mehthod
๋ ์ถ์๋ฉ์๋๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ์๋ธํด๋์ค์ ๊ตฌํ์ ๊ฐ์ ํ์ง ์๋๋ค๋ ๋จ์ ์ด ์๋ค. ์ค์๋ก ๊ตฌํํ์ง ์์๋ ์ ์์ ์ธ ์๋์ ํ๋ฉฐ, ์ด๋ฅผ ๋ง์ ์๊ฐ ์๋ค.
extends interface
์์์ ๋ฌธ์ ๊ฐ ๋๋ ๊ตฌํ์ ๊ฐ์ ์ฑ์ ์ ๋ํ๊ธฐ ์ํด ์๋ก์ด ๊ธฐ๋ฅ์ด ์ ์๋ ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค๊ณ , ๊ธฐ์กด์ ์ธํฐํ์ด์ค๋ฅผ ์์๋ฐ๊ฒ ํ๋ค.
์๋ก์ด ์ธํฐํ์ด์ค๊ฐ ๊ธฐ์กด์ ์ธํฐํ์ด์ค๋ฅผ ์์ํ๋ค.
๊ธฐ์กด ๊ตฌํํด๋์ค๋ค์ ๊ทธ๋๋ก Spec
์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ฒ ๋๋๊ณ , ์๋ก์ด ๊ธฐ๋ฅ์ด ์ถ๊ฐ์ ์ผ๋ก ํ์ํ ํด๋์ค๋ Spec
์ ์์๋ฐ์ Spec2
์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ๊ฒ์ด๋ค.
์ด๋ ๊ฒ ํจ์ผ๋ก์จ ๊ธฐ์กด ์์ค์ ์ํฅ์ ์ฃผ์ง ์๊ณ ๋ฉ์๋ ๊ตฌํ์ ๊ฐ์ ํ๋ฉด์๋ ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ ์ ์๋ค.
1
2
3
public interface Spec2 extends Spec{
void m3();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class C implements Spec2{
// ์๋ธ์ธํฐํ์ด์ค ๊ตฌํ ์ ์ํผ์ธํฐํ์ด์ค๋ ๋ชจ๋ ๊ตฌํํด์ผ ํ๋ค.
@Override
public void m1() {
System.out.println("A.m1()");
}
@Override
public void m2() {
...
}
@Override
public void m3() { // ์ถ๊ฐ
...
}
}
์ธํฐํ์ด์ค ๊ฐ์ ์์์ ํตํด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค. ํ์ง๋ง ๋ง์ฝ ๊ตฌํํด์ผํ๋ ๊ธฐ๋ฅ์ด 100๊ฐ ์ ๋๋๋ค๋ฉด ๋ชจ๋ ๊ตฌํ ํด๋์ค์์ ๋ฉ์๋๋ฅผ ์ฌ์ ์ ํด์ผํ๋ค.
with abstract class
์ด ๋ฐฉ์์ ์์์ ์ธ๊ธํ ๋จ์ ์ ์ปค๋ฒํ ์ ์์ ๋ฟ๋ง ์๋๋ผ ์๋ก์ด ๊ธฐ๋ฅ์ถ๊ฐ ์ ์ฝ๋๊ฐ ๋ ๊ฐ๊ฒฐํด์ง๋ค. ์ผ๋ถ ๋ฉ์๋ ๊ตฌํ์ ์ถ์ํด๋์ค์์ ํ๊ธฐ๋๋ฌธ์ ๋ฉ์๋ ๊ตฌํ์ ํผ๋ก๋๊ฐ ๋ฎ์์ง๋ค. ๊ท๋ชจ๊ฐ ์ปค์ง๋ฉด์ ๊ณตํต๊ธฐ๋ฅ์ ์ธํฐํ์ด์ค๋ก ๋ง์ด ์ถ์ถํด์ผ ํ๋ ๊ฒฝ์ฐ์ ์ค๊ฐ์ ์ถ์ํด๋์ค๋ฅผ ๋๊ณ ์์ ํ๋ ๊ฒ์ด ์ข๋ค. ์ด์ ๊ธ ์์๋ ์ด์๊ฐ์ ๋ฐฉ์์ ํ์ฉํ๋ค.
์ถ์ํด๋์ค๊ฐ ์ธํฐํ์ด์ค๋ฅผ ์์๋ฐ๋๋ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
interface CommonSpec {
m1();
m2();
m3();
m4();
}
abstract class AbstractSpec implements CommonSpec{
@Override
public void m1() {}
@Override
public void m2() {}
@Override
public void m3() {}
@Override
public void m4() {}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class MyClass extends AbstractSpec {
// ๊ตฌํํด๋์ค์์ ํ์ํ ๋ฉ์๋๋ง ์ฌ์ ์ ํ๋ค.
@Override
public void m1() {
System.out.println("MyClass.m1()");
}
@Override
public void m2() {
System.out.println("MyClass.m2()");
}
}
๋๊ธ๋จ๊ธฐ๊ธฐ