공부/SOLID

Open Closed Principle(개방-폐쇄 원칙)

ironk.im 2021. 5. 3. 11:12
반응형

개방 폐쇄 원칙은 소프트웨어의 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다는 원칙이다.

정리하면 기존 코드에 대한 변경 없이 새로운 기능을 추가할 수 있어야 한다.

개방 폐쇄 원칙을 지키게 되면 아래와 같은 장점이 있다.

  1. 유지보수 용이
  2. 재사용성
  3. 확장성

OCP를 위반한 케이스

class DiscountService {
    public int calculateDiscount(int price, String type) {
        switch (type) {
            case "FIXED":
                return price - 1000;
            case "RATE":
                return (int)(price * 0.9);
            default:
                return price;
        }
    }

    public static void main(String[] args) {
        DiscountService discountService = new DiscountService();
        System.out.println(discountService.calculateDiscount(10000, "FIXED")); // 9000
        System.out.println(discountService.calculateDiscount(10000, "RATE"));  // 9000
    }
}

새로운 정책을 추가할 때 마다 calculateDiscount 메소드를 수정해야 한다

해당 메소드는 여러 할인 정책이 있으므로 변경에 닫혀있어야하는 정책을 위반하게 된다

OCP 준수한 케이스

public interface DiscountPolicy {
    boolean supports(String type);
    int discount(int price);
}
public class FixedDiscountPolicy implements DiscountPolicy {
    @Override
    public boolean supports(String type) {
        return "FIXED".equalsIgnoreCase(type);
    }

    @Override
    public int discount(int price) {
        return price - 1000;
    }
}
import java.util.List;

public class DiscountService {
    private final List<DiscountPolicy> policies;

    public DiscountService(List<DiscountPolicy> policies) {
        this.policies = policies;
    }

    public int calculateDiscount(int price, String type) {
        for (DiscountPolicy policy : policies) {
            if (policy.supports(type)) {
                return policy.discount(price);
            }
        }
        return price;
    }
}

----

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        DiscountService discountService = new DiscountService(Arrays.asList(
            new FixedDiscountPolicy(),
            new RateDiscountPolicy()
        ));

        System.out.println(discountService.calculateDiscount(10000, "FIXED")); // 9000
        System.out.println(discountService.calculateDiscount(10000, "RATE"));  // 9000
        System.out.println(discountService.calculateDiscount(10000, "NONE"));  // 10000
    }
}

각 할인 정책은 DiscountPolicy 인터페이스를 구현하게 되기 때문에 DiscountService 는 구현체에 의존하는 것이 아닌 인터페이스에 의존하고 동적 바인딩을 통한 코드 실행 가능해진다

현재 Main 클래스 내에서 의존성을 직접 DiscountService에 주입하고 있지만 이 역할을 Spring IoC 컨테이너가 해주게 되어 기존 코드를 수정하지 않고 정책을 추가할 수 있게 된다

이를 통해 OCP를 준수하게 된다

반응형