728x90
CS
템플릿 메소드(Template Method)
- 템플릿 메서드 패턴은 여러 클래스에서 공통으로 사용하는 메서드를 템플릿화 하여 상위 클래스에서 정의하고, 하위 클래스마다 세부 동작을 다르게 구현하는 패턴이다.
- 즉, 변하지 않는 기능(템플릿)은 상위 클래스에 만들어두고 자주 변경되며 확장할 기능은 하위 클래스에서 만들도록 하여, 상위의 메소드 실행 동작 순서는 고정하면서 세부 실행 내용은 다양화 될 수 있는 경우에 사용된다.
- 템플릿 메소드 패턴은 상속이라는 기술을 극대화하여, 알고리즘의 뼈대를 맞추는 것에 초점을 둔다. 이미 수많은 프레임워크에서 많은 부분에 템플릿 메소드 패턴 코드가 우리도 모르게 적용되어 있다.
템플릿 메서드 패턴 구조
- AbstractClass(추상 클래스)
- 템플릿 메소드를 구현하고, 템플릿 메소드에서 돌아가는 추상 메소드를 선언한다. 이 추상 메소드는 하위 클래스인 ConcreteClass 역할에 의해 구현된다.
- ConcreteClass(구현 클래스)
- AbstractClass를 상속하고 추상 메소드를 구체적으로 구현한다. ConcreteClass에서 구현한 메소드는 AbstractClass의 템플릿 메소드에서 호출된다.
hook 메서드
- 훅(hook) 메소드는 부모의 템플릿 메서드의 영향이나 순서를 제어하고 싶을때 사용되는 메서드 형태를 말한다. 이를 통해 자식 클래스에서 좀 더 유연하게 템플릿 메서드의 알고리즘 로직을 다양화할 수 있다는 특징이 있다.
- 훅 메서드는 추상 메소드가 아닌 일반 메소드로 구현하는데, 선택적으로 오버라이드 하여 자식 클래스에서 제어하거나 아니면 놔두거나 하기 위해서 이다.
템플릿 메소드 패턴 특징
- 패턴 사용 시기
- 클라이언트가 알고리즘의 특정 단계만 확장하고, 전체 알고리즘이나 해당 구조는 확장하지 않도록 할 때
- 동일한 기능은 상위 클래스에서 정의하면서 확장, 변화가 필요한 부분만 하위 클래스에서 구현할 때
- 패턴 장점
- 클라이언트가 대규모 알고리즘의 특정 부분만 재정의하도록 하여, 알고리즘의 다른 부분에 발생하는 변경 사항의 영향을 덜 받도록 한다.
- 상위 추상 클래스로 로직을 공통화하여 코드의 중복을 줄일 수 있다.
- 서브 클래스의 역할을 줄이고, 핵심 로직을 상위 클래스에서 관리하므로서 관리가 용이해진다.
- 헐리우드 원칙(Hollywood Principle) : 고수준 구성요소에서 저수준을 다루는 원칙
- 패턴 단점
- 알고리즘의 제공된 골격에 의해 유연성이 제한될 수 있다.
- 알고리즘 구조가 복잡할수록 템플릿 로직 형태를 유지하기 어려워진다.
- 추상 메소가드가 많아지면서 클래스의 생성, 관리가 어려워질 수 있다.
- 상위 클래스에서 선언된 추상 메소드를 하위 클래스에서 구현할 때, 그 메소드가 어느 타이밍에서 호출되는지 클래스 로직을 이해해야 할 필요가 있다.
- 로직 변화가 생겨 상위 클래스를 수정할 때, 모든 서브 클래스의 수정이 필요 할수도 있다.
- 하위 클래스를 통해 기본 단계 구현을 억제하여 리스코프 치환 법칙을 위반할 여지가 있다.
할리우드 원칙 준수
- 할리우드 원칙(Hollywood Priciple) 이란 고수준 모듈(추상클래스, 인터페이스)에 의존하고 고수준 모듈에서 연락(메소드 실행) 하라는 원칙이다.
- 객체 끼리 이상하게 얼키고 설켜, 의존성이 복잡하게 꼬여있는 것을 의존성 부패(dependency rot)라고 부르는데, 헐리우드 원칙을 활용하면 의존성 부패를 방지할 수 있게 된다.
비슷한 디자인 패턴 비교 - Strategy vs Temaplate Method
- 전략 패턴은 합성(composition)을 통해 해결책을 강구하며, 템플릿 메서드 패턴은 상속(inheritance)을 통해 해결책을 제시한다.
- 그래서 전략 패턴은 클라이언트와 객체 간의 결합이 느슨한 반면, 템플릿 메서드 패턴에서는 두 모듈이 더 밀접하게 결합된다. (결합도가 높으면 안좋다)
- 전략 패턴에서는 대부분 인터페이스를 사용하지만, 템플릿 메서드 패턴에서는 주로 추상 클래스나 구체적인 클래스를 사용한다.
- 전략 패턴에서는 전체 전략 알고리즘을 변경할 수 있지만, 템플릿 메서드 패턴에서는 알고리즘의 일부만 변경되고 나머지는 변경되지 않은 상태로 유지된다.(템플릿에 종속)
참조
https://inpa.tistory.com/entry/GOF-💠-템플릿-메소드Template-Method-패턴-제대로-배워보자
C++
함수의 오버로딩(Overloading)
- C++에서는 같은 이름을 가진 함수가 여러개 존재해도 된다. C++에서는 같은 이름의 함수를 호출했을때 사용하는 인자를 보고 결정하게 된다. 함수의 이름이 같더라도 인자가 다르면 다른 함수라고 판단하기 때문에 오류가 발생하지 않는다.
C++ 컴파일러에서 함수를 오버로딩하는 과정
- 자신과 타입이 정확히 일치하는 함수를 찾는다.
- 정확히 일치하는 타입이 없는 경우 아래와 같은 형변환을 통해서 일치하는 함수를 찾아본다.
- Char, unsigned char, short 는 int 로 변환된다.
- Unsigned short 는 int 의 크기에 따라 int 혹은 unsigned int 로 변환된다.
- Float 은 double 로 변환된다.
- Enum 은 int 로 변환된다.
- 위와 같이 변환해도 일치하는 것이 없다면 아래의 좀 더 포괄적인 형변환을 통해 일치하는 함수를 찾는다.
- 임의의 숫자(numeric) 타입은 다른 숫자 타입으로 변환된다.
- ex) float → int
- Enum 도 임의의 숫자 타입으로 변환된다.
- ex) Enum → double
- 0은 포인터 타입이나 숫자 타입으로 변환된다.
- 포인터는 void 포인터로 변환된다
- 임의의 숫자(numeric) 타입은 다른 숫자 타입으로 변환된다.
- 유저 정의된 타입 변환으로 일치하는 것을 찾는다.
- 만약에 컴파일러가 위 과정을 통하더라도 일치하는 함수를 찾을 수 없거나 같은 단계에서 두 개 이상이 일치하는 경우에 모호하다(ambiguous) 라고 판단해서 오류를 발생하게 된다.
생성자(Constructor)
- 생성자는 기본적으로 객체 생성시 자동으로 호출되는 함수라고 볼 수 있다. 이 때 자동으로 호출되면서 객체를 초기화 해주는 역할을 담당하게 된다.
디폴트 생성자(Default Constructor)
- 디폴트 생성자는 인자를 하나도 가지지 않는 생성자인데, 클래스에서 사용자가 어떠한 생성자도 명시적으로 정의하지 않았을 경우에 컴파일러가 자동으로 추가해주는 생성자이다.
- 물론 컴파일러가 자동으로 생성할 때에는 아무런 일도 하지 않게 된다. 그렇기에 쓰레기 값이 나온다.
- C++ 11 이전에는 디폴트 생성자를 사용하고 싶을 경우 그냥 생성자를 정의하지 않는 방법 밖에 없었다. C++ 11 부터는 명시적으로 디폴트 생성자를 사용하도록 명시할 수 있다.
- 생성자의 선언 바로 뒤에 = default 를 붙여준다면, 디폴트 생성자를 정의하라고 컴파일러에게 명시적으로 알려줄 수 있다.
생성자 오버로딩
- 생성자 역시 함수이기 때문에 함수의 오버로딩이 적용될 수 있다.
- 해당 클래스의 객체를 여러가지 방식으로 생성할 수 있게 된다.
728x90
'Study > TIL(Today I Learned)' 카테고리의 다른 글
24.09.02 CS, 언리얼 (1) | 2024.09.02 |
---|---|
24.08.30 CS, C++ (0) | 2024.08.30 |
24.08.27 CS, C++ (0) | 2024.08.27 |
24.08.26 CS, C++ (0) | 2024.08.26 |
24.08.23 CS (0) | 2024.08.23 |