Java 에서 Interface 확장관련 질문 드립니다.(디자인 패턴)


디자인패턴에 관한 질문인 것 같습니다 ^

하나의 인터페이스를 여러개의 클래스가 구현하고 있는 상황에서

특정한 하나의 클래스에서 새로운 구현체를 만들어야 할 경우 (인터페이스에 새로운 메소드 추가)

어떻게 새로운 메소드를 추가할 것이며 다른 클래스에 영향을 주지 않도록 확장하는 방법은 무엇일까요??

또한, 호출방식이 변경되어도 좋지만 최대한 기존 호출방식이 변경되지 않도록 할 수 는 없을까요?

샘플코드입니다~ 굉장히 간단합니다~

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>();
    }
}
  • 2016년 03월 29일에 작성됨

조회수 456


2 답변


좋아요
3
싫어요
채택취소하기

질문이 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

  • 2016년 03월 29일에 작성됨
    프로그래밍 언어를 좋아하는 프로그래머

  • 답변 감사드립니다~ 적용해 봐야겠네요~    OKIHOUSE   2016.3.29 19:14     

거의 다 알고 계시는거 같은데...

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();
 }
}

※ 코드 확인은 안했습니다.

  • 2016년 03월 29일에 작성됨

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close