inflearn

[인프런] 김영한의 자바 기본 강의 섹션12. 다형성과 설계 (240117)

hail2y 2024. 1. 17. 16:47

지난 글에서 다형성이 되게 이해가 잘 돼서 신나서 강의 들었다고 쓴 것 같은데 바로 다음에서 막히고 슬퍼서 쉬엄쉬엄 공부했다.. 강의 보고 코드 쳐 보고 또 강의 보고 또 쳐 보고를 반복하고 있는데 개념은 이해가 가지만 아직 객체지향이 익숙하지 않아서인지 내 코드처럼 느껴지진 않는다. 더 연습이 필요한 거겠지 부단히 노력해 보자! 관련 문제들도 찾아서 풀어봐야겠다 다시 코드 쳐 본 다음에!

1/17 다형성과 설계 필기

자동차의 역할과 구현을 분리한 이유는 클라이언트인 운전자 나를 위한 것이다. 역할을 부여했기 때문에 클라이언트는 내부구조를 알 필요도 없고 클라이언트의 코드를 변경하지 않아도 된다.(=나한테는 영향이 없다.) 그렇기 때문에 유연하고 변경에 용이하며 이렇게 함으로써 client인 내가 제일 좋다.

 

클라이언트는 구현객체가 아닌 인터페이스에만 의존한다. 결국에는 다형성 덕분에 가능했는데 사용자가 호출하는 과정을 보면, 인터페이스를 호출했을 때 오버라이딩 된 메서드가 호출된다. 이것은 객체 인스턴스를 실행시점에 유연하게 변경 가능하다는 것이다. 이 과정에서 클라이언트의 코드는 변경할 필요가 없다. 

 

즉, 클라이언트가 인터페이스에 의존하는 것이므로 인터페이스를 안정적으로 잘 설계하는 것이 가장 중요하다. 

  • 요청하는 입장: client
  • 응답하는 입장: 서버
    (서버가 클라이언트 역할을 수행하기도 한다. )

꿀팁!

  • 값(데이터)를 대입할 때 set.. 이런 메서드를 자주 이용해서 인텔리제이에서 set만 쳐도 메서드를 자동 생성해 준다.

문제 풀면서:

멤버변수를 알고 있다(=사용한다)는 것은 의존하는 것이다.

OCP(Open-Closed Principle) 원칙

좋은 객체지향 설계원칙 중의 하나인데, 기존의 코드 수정 없이 새로운 기능을 추가할 수 있다. 

open for extension : 새로운 기능의 추가나 변경사항이 생겼을 때 기존 코드는 확장할 수 있어야 한다.
closed for modification : 기존의 코드는 수정되지 않아야 한다. 

 

핵심 클라이언트의 코드는 전혀 변경되지 않는다. 기능을 확장해도 main() 일부를 제외한 프로그램의 핵심 부분의 코드는 전혀 수정하지 않아도 된다. 다형성을 활용하고 역할과 구현을 잘 분리하면 새로운 기능을 추가해도 대부분의 핵심 코드들을 그대로 유지할 수 있다.  

 

ex) 계산을 느리게 하는 컴퓨터가 있는데, 더 효율적으로 작동시키기 위해서 다른 클래스로 갈아끼우면 그 계산식을 사용하는 클라이언트의 코드는 전혀 변경하지 않아도 된다.

 

cf. 디자인 패턴 中 전략 패턴

알고리즘을 클라이언트 코드의 변경 없이 쉽게 교체 가능하다. 전략을 정의하는 인터페이스와 전략의 구체적인 구현. 클라이언트 코드의 변경 없이 손쉽게 전략을 교체할 수 있다. 

변하지 않는 부분과 변하는 부분을 잘 구분하는 게 중요하다. 

문제 풀면서:

  • KakaoPay, NaverPay 구체적인 객체들을 직접적으로 의존하는 것이 문제이다.
  • 한번에 여러가지 하는 게 있다면 잘게 쪼개보자!
    - 결제 수단을 찾아서 선택하는 거랑
    - 각 결제 수단의 pay를 실행하는 거랑 => 중복 => 메서드로 뽑아볼 수 있다.
if (option.equals("kakao")) {
	KakaoPay kakaoPay = new KakaoPay(); // 결제 수단 선택
    result = kakaoPay.pay(amount); // 결제 처리 (pay 실행)
} else if (option.equals("naver")) {
	NaverPay naverPay = new NaverPay();  // 결제 수단 선택
    result = naverPay.pay(amount); // 결제 처리 (pay 실행)
} else {
	System.out.println("결제 수단이 없습니다."); // 결제 수단 선택
    result = false; // 결제 처리 (pay 실행)
}

정리하면,

역할과 구현을 분리하는 것이 중요하다. 디자인패턴의 대부분과 스프링 프레임워크도 다 다형성으로 활용한다. 구현에 의존하는 것이 아니라 역할에 의존해야 기존 코드의 변경 없이 런타임 변경이 가능하다. 

--끝--