1. 인터페이스 분리 원칙이란?
•
‘클라이언트가 사용하지 않을 불필요한 메서드를 강제로 구현하게 해서는 안 된다’는 의미이다.
•
클라이언트가 사용하지 않을 메서드를 강제로 구현하는 일이 없을 때까지 하나의 인터페이스를 2개 이상의 인터페이스로 분할하는 원칙을 의미한다.
예를 들어 connect, socket, http 총 세 가지 메서드를 가지는 Connection 인터페이스가 있다고 가정해보자. 이때 어떤 클라이언트는 HTTP를 통한 연결만을 위해 이 인터페이스를 구현하고 싶을 수도 있다. 이런 경우 socket 메서드는 불필요하므로 클라이언트가 이 메서드를 비워둘 것이다. 이렇게 되면 잘못된 설계이다. 이러한 상황을 방지하기 위해 Connection 인터페이스를 2개로 나누어야 한다. 즉, socket 메서드를 가지는 SocketConnection 인터페이스와 http 메서드를 가지는 HttpConnection 인터페이스로 나누어야 한다. 두 인터페이스는 공통된 메서드인 connect를 가지는 Connection 인터페이스를 상속받을 것이다.
2. 인터페이스 분리 원칙 예제
인터페이스 분리 원칙을 따르지 않는 경우
•
Connection 인터페이스는 다음과 같이 세 가지 메서드를 정의한다.
package bad;
public interface Connection {
public void socket();
public void http();
public void connect();
}
Java
복사
•
WwwPingConnection 클래스는 서로 다른 웹사이트를 HTTP로 핑(ping)한다. 따라서 http 메서드는 필요하지만 socket 메서드는 필요 없다. 이때 의미 없는 방법으로 socket 메서드를 구현한 것을 주목하자. WwwPingConnection 클래스는 Connection 인터페이스를 구현하므로 socket 메서드도 강제로 구현해야 한다.
package bad;
public class WwwPingConnection implements Connection {
private final String www;
public WwwPingConnection(String www) {
this.www = www;
}
@Override
public void http() {
System.out.println("Setup an HTTP connection to " + www);
}
@Override
public void connect() {
System.out.println("Connect to " + www);
}
// 이 메서드는 인터페이스 분리 원칙에 맞지 않는다.
// 이 클래스는 socket 메서드가 필요하지 않지만 강제로 재정의해야 한다.
// 불필요한 자원 낭비!
@Override
public void socket() { }
}
Java
복사
•
다음 코드를 확인해보자
package bad;
public class WwwPingConnection implements Connection {
private final String www;
public WwwPingConnection(String www) {
this.www = www;
}
@Override
public void http() {
System.out.println("Setup an HTTP connection to " + www);
}
@Override
public void connect() {
System.out.println("Connect to " + www);
}
// 이 메서드는 인터페이스 분리 원칙에 맞지 않는다.
// 이 클래스는 socket 메서드가 필요하지 않지만 강제로 재정의해야 한다.
// 불필요한 자원 낭비!
@Override
public void socket() { }
}
=== 결과 ==
Approach that doesn't follow ISP:
Setup an HTTP connection to www.yahoo.com
Connect to www.yahoo.com
Java
복사
이 코드로 무엇을 얻을 수 있을까? 작동하기는 하지만 아무 의미가 없는 코드나, HTTP 엔드포인트가 없기 때문에 connect 메서드에 의해 발생하는 예외 또는 ‘소켓은 지원하지 않습니다!’와 같은 예외를 발생시킬 수도 있을 것이다.
인터페이스 분리 원칙을 따르는 경우
•
인터페이스 분리 원칙을 준수하려면 Connection 인터페이스를 분리해야 한다. connect 메서드는 모든 클라이언트에 필요하므로 이 메서드는 Connection 인터페이스에 남긴다.
package good;
public interface Connection {
public void connect();
}
Java
복사
•
http와 socket 메서드는 다음과 같이 Connection 인터페이스를 확장하는 별도의 인터페이스에 포함된다.
package good;
public interface HttpConnection extends Connection {
public void http();
}
Java
복사
package good;
public interface SocketConnection extends Connection {
public void socket();
}
Java
복사
이렇게 하면 WwwPingConnection 클래스는 HttpConnection 인터페이스만 구현하여 http 메서드를 사용할 수 있다.
package good;
public class WwwPingConnection implements HttpConnection {
private final String www;
public WwwPingConnection(String www) {
this.www = www;
}
@Override
public void connect() {
System.out.println("Setup an HTTP connection to " + www);
}
@Override
public void http() {
System.out.println("Connect to " + www);
}
}
Java
복사
⇒ 이렇게 하면 모든 코드는 인터페이스 분리 원칙을 따른다.