Java 에서 Interface 확장관련 질문 드립니다.(디자인 패턴)
조회수 2746회
디자인패턴에 관한 질문인 것 같습니다 ^
하나의 인터페이스를 여러개의 클래스가 구현하고 있는 상황에서
특정한 하나의 클래스에서 새로운 구현체를 만들어야 할 경우 (인터페이스에 새로운 메소드 추가)
어떻게 새로운 메소드를 추가할 것이며 다른 클래스에 영향을 주지 않도록 확장하는 방법은 무엇일까요??
또한, 호출방식이 변경되어도 좋지만 최대한 기존 호출방식이 변경되지 않도록 할 수 는 없을까요?
샘플코드입니다~ 굉장히 간단합니다~
public interface Phone {
public void call();
}
public class LG implements Phone {
@Override
public void call(){
System.out.println("calling...");
}
}
public class Apple implements Phone {
@Override
public void call(){
System.out.println("calling...");
}
}
public interface Dmb {
public List<String> channels();
}
굉장히 간단한 코드입니다.
LG 의 경우 DMB 가 존재하며, Apple 의 경우 DMB가 없다고 가정하겠습니다~
여기서 DMB라는기능을 LG에 포함시켜야 하는데 이 경우 어떤식으로 작업하는지가 궁금합니다.
기존의 호출방식입니다.
Phone phone = new Apple();
phone.call();
좀 더 나아가 LG class에서 다음과 같이 작업했다고 할 경우에 해당 메소드를 어떤식으로 호출하는지도 궁금합니다.
public class LG implements Phone, Dmb {
@Override
public void call(){
System.out.println("calling...");
}
@Override
public List<String> channels(){
return new ArrayList<String>();
}
}
-
(•́ ✖ •̀)
알 수 없는 사용자
2 답변
-
질문이 2가지 인것 같네요.
- 인터페이스에 새 메소드가 추가되는 경우 해당 인터페이스를 구현하는 구현 클래스들의 변경을 어떻게 최소화 하는가?
위 문제는 Expression_problem이라고 불립니다.
디자인 패턴으로 위 문제를 해결하는 방법은 Visitor pattern을 사용하는 것인데, 이는 Visitor pattern에 맞춰서 코드를 변경해야 하기 때문에 불필요한 복잡도가 추가되게 됩니다.
위 문제를 조금 더 정확하게 해결하는 방법으로는 Type Class를 사용하면 되는데 안타깝게도 자바에서는 지원되지 않습니다.
다른 방법으로는 Java 8부터 포함된 Default method를 사용해서 기본 구현을 인터페이스에 추가하는 방법이 있습니다.
이 방법은 기본 구현 외에 것을 하려면 다시 처음 문제로 돌아가게 됩니다.
다음 질문은,
- 구현체들 중 특정 인터페이스(DMB)만 구현한 클래스에서 메소드를 어떻게 호출하느냐?
위에 다른분이 답변 주신것 처럼 캐스팅 해서 호출하는 방법이 있겠으나, 이 역시 근본적인 해결책은 아닙니다. 타입별로 분기를 를 제거하기 위해서 다형성을 사용했는데 다시 분기를 타야 하니 말이죠.
Phone의 하위 구현체가 일부 인터페이스를 더 구현한다고 하면 이미 해당 구현체는 더이상
Phone type
을 기대하는 곳에서Dmb type
의 메서드를 호출하는 것 자체가 이상한 구현으로 보입니다.아래 글을 읽어보시면 문제 이해와 해결에 도움이 많이 될거라 생각됩니다.
참고: http://koerbitz.me/posts/Sum-Types-Visitors-and-the-Expression-Problem.html
-
(•́ ✖ •̀)
알 수 없는 사용자
-
거의 다 알고 계시는거 같은데...
DMB가 필요할땐 Dmb 인터페이스로 캐스팅 하시면 되죠.
ArrayList<Phone> list = new ArrayList<Phone>(); list.add(new LG()); list.add(new Apple()); for(Phone phone : list) { if (phone instanceof Dmb) { Dmb dmb = (Dmb)phone; dmb.channels(); } }
※ 코드 확인은 안했습니다.
-
(•́ ✖ •̀)
알 수 없는 사용자
-
댓글 입력