새로운 내용을 공부할 때
새로운 내용의 공부를 시작할 때 용어의 정의를 이해하지 못하거나 정확하게 알지 못한다면 그 용어가 포함된 문장을 이해하지 못합니다.
작은 단어 하나가 내용을 이해하지 못하게 하기 때문에 용어를 정확하게 이해하는 것이 중요합니다.

1 분 소요

📌 2025-03-08 TIL

1. 오늘의 학습 주제

  • 변경에는 닫혀 있고, 확장에는 열려있다는 의미를 다시 생각해 보았습니다.

2. 학습 내용

클래스는 확장에는 열려있고, 수정에는 닫혀있어야 한다.

클래스를 설계할 때 확장에는 열려있도록 하고 수정에는 닫혀있도록 해야한다는 설계 원칙입니다.

확장에는 열려있도록 하기 위해서는 구현체에 의존하지 않고 추상화 역할에 의존해야합니다.

수정에는 닫혀있기 위해서는 정해진 틀을 만들어야하고 그것을 고정해야합니다.

고정된 틀

  1. 조건이 일치하는지 확인한다
  2. 조건이 만족하면 실행한다.

변경되는 틀

  1. 조건의 구체적인 내용
  2. 실행되는 내부 로직

객체지향 프로그래밍을 할 때 중요한 것은 전체 프로세스를 보면서 변경되는 것과 변경되지 않은 것을 구분하는 시야를 갖는거라고 생각이 들었습니다.

if(State.EMPTY == input) {
  doSometing();
  return;
}
if(State.USING == input) {
  doSometing();
  return;
}
if(State.SUSPEND == input) {
  doSometing();
  return;
}
throw new IlligalArgumentException("지원하지 않은 타입입니다.");

예를 들면, 위 코드는 조건을 확인하는 것은 동일합니다.

그리고 그 조건에 따라 실행되는 메서드가 있습니다.

변경되는 것 : 입력된 상태(구체), 실행되는 메서드의 내부 로직(구체)

변경되지 않는 것: 조건을 확인하는 행위, 메서드를 실행하는 행위

기존 코드를 변경하지 않고 추가되는 조건과 내부 로직을 적용하기 위해서 여러가지 디자인 패턴을 사용할 수 있습니다.

클래스 상속으로 여러가지 방식을 클래스를 만들어서 사용하는 템플릿 패턴

사용할 방식을 클라이언트가 선택하는 콜백 패턴

다형성을 활용하여 Enum 과 인터페이스를 활용하는 방법등이 있다는 것을 알게되었습니다.

// 메뉴 검색 기능을 위한 인터페이스 정의
public interface MenuSelector {
    boolean matches(String input);
}

// Enum 정의: 각 메뉴는 별칭(alias) 리스트를 가지고 있음
public enum Menu implements MenuSelector {
    뼈해장국(List.of("뼈", "뼈해장국")),
    우거지해장국(List.of("우거지", "우거지해장국")),
    황태해장국(List.of("황태", "황태해장국", "맑은거요"));

    private final List<String> aliases;

    Menu(List<String> aliases) {
        this.aliases = aliases;
    }

    // 인터페이스 구현: 입력 값이 해당 메뉴의 별칭에 포함되면 true를 반환
    @Override
    public boolean matches(String input) {
        return aliases.contains(input);
    }

    // static 메서드: 입력 값과 일치하는 메뉴를 찾기 위해 enum의 values() 사용
    public static Menu findByAlias(String input) {
        return Arrays.stream(Menu.values())
                     .filter(menu -> menu.matches(input))
                     .findFirst()
                     .orElseThrow(() -> new IllegalArgumentException("메뉴를 다시 물어봅니다.: " + input));
    }
}

// 테스트를 위한 메인 클래스
class 음식점 {
    public static void main(String[] args) {
        String input = "맑은거요";
        Menu selectedMenu = Menu.findByAlias(input);
        System.out.println("네~: " + selectedMenu);
    }
}

이처럼 OCP는 고정 틀과 변경 틀을 기준을 잡아서 어떤 방식으로 활용할 것인지 결정하는 것이 핵심이라고 생각합니다.

댓글남기기