객체 지향 설계란 변화와 확장에 유연한 설계
라고 할 수 있다.
객체 지향적으로 잘 설계한 코드는 변화와 확장을 하더라도, 기존의 코드는 최대한 건들이지 않게 된다는 것!
이런 객체 지향 프로그래밍을 하기 위해서는 크게 2가지가 필요하다.
A 클래스가 B 클래스에 의존한다.
= A 클래스에서 B 클래스에 정의된 속성이나 기능을 가져와 사용하고 있다.
이때 B 클래스에 변경 사항이 발생하거나, B 클래스가 아닌 C 클래스로 교체해야 하는 상황이 발생한다면?
=> B 클래스에 의존하고 있던 A 클래스의 코드 변경이 불가피하다.
코드가 점점 더 길어지고 복잡해지는데, 구현 클래스에 계속 의존하다 보면 코드를 수정하거나 유지/보수하는데 많은 어려움이 있다.
따라서 구현(클래스)에 의존하지 않고, 역할(인터페이스)에 의존해야 한다.
이때의 구현 클래스는 B, C 클래스(구체적인 클래스)를 의미하고, 역할 클래스는 B, C의 역할을 담고 있는 인터페이스를 말한다.
인터페이스 = 역할과 구현의 분리
인터페이스는 객체들이 반드시 해야할 역할을 규정해준다.
그러므로 인터페이스를 통해, 역할과 구현을 분리시켜야 한다.
[ 예제 코드 ]
public class Test{
public static void main(String[] args) {
User user = new User(); // User 클래스 객체 생성
// user.callProvider(new Provider());
user.callProvider(new Provider2());
}
}
class User { // User 클래스
// public void callProvider(Provider provider) {
// provider.call(); // Provider 클래스에 의존한다.
// }
public void callProvider(Provider2 provider) {
provider.call(); // Provider2 클래스에 의존한다.
}
}
class Provider { // Provider 클래스
public void call() {
System.out.println("무야호~");
}
}
class Provider2 { // Provider2 클래스
public void call() {
System.out.println("야호~");
}
}
interface Cover { // 인터페이스 정의
public abstract void call();
}
public class Test {
public static void main(String[] args) {
User user = new User();
user.callProvider(new Provider2());
}
}
class User {
public void callProvider(Cover cover) { // 매개변수의 다형성 활용
cover.call();
}
}
class Provider implements Cover {
public void call() {
System.out.println("무야호~");
}
}
class Provider2 implements Cover {
public void call() {
System.out.println("야호~");
}
}
[ 추가적인 예시 -1 ]
어떤 식당에서 할인 이벤트를 진행하고 있다. 이때 이벤트는 상시 또는 불특정하게 진행되며 새로운 이벤트가 생성되기도 하며 없어지기도 한다.
현재 존재하는 이벤트는 두 가지로 다음과 같다.
만약 A, B 객체에 직접 의존하면, 나중에 이벤트가 사라지거나 추가될 때 많은 부분을 수정해야 한다.
즉 구현에 의존하지 않고, 역할에 의존해야 한다.
역할에 의존하기 위해, interface(역할)을 생성하고 이벤트들이 interface를 구현하도록 한다.
모든 이벤트들은 interface에서 강제한 기능을 구현하고 있고, interface 타입으로 이벤트를 받아 이를 실행할 수 있어 코드의 수정이 최소화된다.
[ 추가적인 예시 -2 ]
로미오와 줄리엣 연극을 한다고 생각해보자.
나는 로미오 역할을 맡았고, 로미오와 줄리엣 역할마다 5명의 연기자가 있다고 생각해보자.
나는 공연동안 5명의 줄리엣을 만나게 될 것이다.
줄리엣 연기자는 "김채은", "빅채은"..등이 있다.
(역할 = 줄리엣/ 구현 = 줄리엣 역할을 연기하는 5명의 연기자분)
내가 연습을 할 때, "김채은" 분에게 맞춰 모든 액션과 애드리브를 만들어뒀다면(= "김채은" 분께 의존했다)
나중에 실전에서 "박채은" 배우와 만났을 때는 새롭게 설정해야할 것도 많아진다.
따라서 나는 어떤 줄리엣 배우를 만나게 될 지 모르니, 배우에 의존할 것이 아니라, 줄리엣이라는 역할에 의존해서 연습을 해야할 것이다.
인터페이스를 생성한 다음, 인터페이스 타입으로 객체를 선언한다.