본문 바로가기

객체지향설계 5원칙(S.O.L.I.D)

I. 인터페이스 분리 원칙(Interface Segregation Principle)

인터페이스 분리 원칙이란?

클라이언트가 자신이 이용하지 않는 메서드에 의존하지 않아야 한다 라는 원칙이다. 어떠한 인터페이스가 서로 다른 메서드를 사용하는 클라이언트가 사용한다면 좋은 설계가 아니다. 인터페이스의 변화에 따라 모든 클라이언트에 영향을 줄 수 있기 때문에 사용 기능에 따라 인터페이스를 분리하는 것이 내부 의존도를 낮출 수 있고, 구현 클래스가 관심있는 메소드에 대해서만 관심을 가질 수 있다.

인터페이스 분리 원칙이 지켜지지 않은 코드

public enum Duty {
    PERSONAL_FINANCE("개인 금융 업무"),
    ENTERPRISE_FINANCE("기업 금융 업무"),
    PB("Private Banking 업무");

    private final String desc;

    Duty(String desc) {
        this.desc = desc;
    }

    public String description() {
        return this.desc;
    }
}

public interface Bank {
    void doPersonalFinance();
    void doEnterpriseFinance();
    void doPrivateBanking();

    default String msg(String bankName, Duty duty) {
        return String.format("%s는 %s를 합니다.", bankName, duty.description());
    }
}

public class HappyBank implements Bank {
    @Override
    public void doPersonalFinance() {
        System.out.println(this.msg(this.getClass().getSimpleName(), Duty.PERSONAL_FINANCE));
    }

    @Override
    public void doEnterpriseFinance() {
        System.out.println(this.msg(this.getClass().getSimpleName(), Duty.ENTERPRISE_FINANCE));
    }

    @Override
    public void doPrivateBanking() {
        //
    }
}

public class UnhappyBank implements Bank {
    @Override
    public void doPersonalFinance() {
        System.out.println(this.msg(this.getClass().getSimpleName(), Duty.PERSONAL_FINANCE));
    }

    @Override
    public void doEnterpriseFinance() {
        System.out.println(this.msg(this.getClass().getSimpleName(), Duty.ENTERPRISE_FINANCE));
    }

    @Override
    public void doPrivateBanking() {
        System.out.println(this.msg(this.getClass().getSimpleName(), Duty.PB));
    }
}

개인 금융 업무, 기업 금융 업무, PB 업무 세 가지의 업무를 하는 Bank 인터페이스를 생성하였다. Bank 인터페이스를 구현하는 구현체들은 해당 업무를 하지 않더라도 인터페이스 상에 정의되어 있는 메서드를 구현해야만 한다.

인터페이스 분리 원칙 적용

public interface BankMessage {
    default String msg(String bankName, Duty duty) {
        return String.format("%s는 %s를 합니다.", bankName, duty.description());
    }
}

public interface BankPersonalFinance extends BankMessage {
    void doPersonalFinance();
}

public interface BankEnterpriseFinance extends BankMessage {
    void doEnterpriseFinance();
}

public interface PrivateBankingFinance extends BankMessage {
    void doPrivateBanking();
}

public class SunnyBank implements BankPersonalFinance, BankEnterpriseFinance {
    @Override
    public void doPersonalFinance() {
        System.out.println(this.msg(this.getClass().getSimpleName(), Duty.PERSONAL_FINANCE));
    }

    @Override
    public void doEnterpriseFinance() {
        System.out.println(this.msg(this.getClass().getSimpleName(), Duty.ENTERPRISE_FINANCE));
    }
}

public class RainyBank implements BankPersonalFinance, BankEnterpriseFinance, PrivateBankingFinance {
    @Override
    public void doPersonalFinance() {
        System.out.println(this.msg(this.getClass().getSimpleName(), Duty.PERSONAL_FINANCE));
    }

    @Override
    public void doEnterpriseFinance() {
        System.out.println(this.msg(this.getClass().getSimpleName(), Duty.ENTERPRISE_FINANCE));
    }

    @Override
    public void doPrivateBanking() {
        System.out.println(this.msg(this.getClass().getSimpleName(), Duty.PB));
    }
}

 

업무에 따라 인터페이스를 분리하여 클라이언트가 사용하는 인터페이스를 구현하도록 변경하였다. 변경된 코드는 기능이 추가되더라도 클라이언트 객체에서 인터페이스를 구현하면 되기 때문에 인터페이스를 사용하는 다른 클라이언트에게 영향을 주지 않는다. 또한, 사용하고자 하는 메서드만 구현하기 때문에 객체의 응집도가 높다고 할 수 있다.

 

https://github.com/haedoang/solid.git