특정 작업을 처리하는 일부분을 서브 클래스로 캡슐화하여 전체적인 구조는 바꾸지 않으면서 특정 단계에 수행하는 내용을 바꾸는 패턴이다.
예를들어 HTTP와 SMTP Client 프로그램의 경우, 주고받는 메세지의 내용이 다르지만 둘 다 인터넷 프로토콜을 이용해 서버에 요청을 전달하고 결과를 수신하는 점에서 동일하다.
이와 같이 두개 이상의 프로그램이 같은 골격 하에 동작한다고 가정할 때 기본 골격에 해당하는 알고리즘은 일괄적으로 처리하면서 각 프로그램에 다른 부분은 따로 만들고 싶을때 템플릿 매서드 패턴을 사용한다.
※ 디자인 패턴에서의 템플릿: 변하지 않는 것을 의미한다.
알고리즘의 구조를 매서드에 정의하고, 하위 클래스에서 알고리즘 구조의 변경없이 알고리즘을 재정의한다. 변하지 않는 기능은 슈퍼클래스 (상위 클래스)에 만들어 두고 자주 변경하며 확장할 기능은 서브 클래스에서 만들도록 한다.
템플릿 매서드를 구현하고, 템플릿 매서드에 돌아가는 추상 메서드를 선언한다. 이 추상 메서드는 하위 클래스 (구현된 클래스)인 ConcreteClass 역할에 의해 구현된다.
AbstractClass를 상속하고 추상 매서드를 구체적으로 구현한다. 이곳 ConcreteClass에서 구현한 메서드가 AbstractClass의 템플릿 메서드에서 호출된다.
hook 메서드는 부모 템플릿 매서드의 영향이나 순서를 제어하려고 할 때 사용되는 매서드의 형태이다. 이를 통해 자식 클래스에서 더 유연하게 템플릿 매서드의 알고리즘 로직을 다양화 할 수 있다.
훅 매서드는 추상 매서드가 아닌, 일반 메서드로 구현한다. 이는 선택적으로 자식 클래스에서 오버라이드 해서 제어하거나 혹은 그냥 놔두기 위해서이다.
출처
1. https://coding-factory.tistory.com/712
2. https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A9%94%EC%86%8C%EB%93%9CTemplate-Method-%ED%8C%A8%ED%84%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EC%9E%90
3. https://velog.io/@letskuku/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A9%94%EC%84%9C%EB%93%9C-%ED%8C%A8%ED%84%B4Template-Method-Pattern
4. https://engineering.linecorp.com/ko/blog/templete-method-pattern
팩토리 매서드 패턴은 객체를 생성하는 클래스를 따로 두는 것 이다. 실질적인 클래스의 구현은 하위 클래스에서 완성되며 이 경우 상위 클래스는 하위 클래스의 구현 내용을 모르더라도 사용이 가능하다.
다시말해 다양한 구현체(Product)가 있고, 그 중 특정한 구현체를 만드는 다양한 팩토리 (Creator)를 제공할 수 있다.
팩토리 매서드의 사용 목적은 클래스 간의 결합도(Coupling)를 낮추기 위해서다. 결합도라는 것은 클래스의 변경할 부분이 생겼을 때 얼마나 다른 클래스에 영향을 주는 것인가 를 생각하면 된다. 팩토리 매서드를 통해 직접 객체를 생성후 사용하는 것을 서브 클래스에 위임함으로써 의존성을 제거하며 결합도 또한 낮출 수 있게 된다.
※ 결합도(Coupling)는 낮을 수록 좋고, 응집도(Cohesion)는 높을수록 좋다.
정리
Product 인터페이스: Icecream
Concrete Product 클래스: Babbambar, Pigbar
Creator 추상 클래스: IcecreamFactory
Concrete Creator 클래스: BabbambarFactory, PigbarFactory
아이스크림 공장이 있고 아이스크림을 만들어 낸다고 가정하여 팩토리 매서드를 구현하였다.
아이스크림 제품에 대한 인터페이스를 만들어주고 여기서 나오는 아이스크림(바밤바 & 돼지바) 그리고 향후 만들어질 아이스크림들은 이 인터페이스를 구현해야 한다.
Icecream 인터페이스를 구현한 Babbambar 클래스와
마찬가지로 Icecream 인터페이스를 구현한 Pigbar 클래스를 만들어 준다.
이제 추상 클래스인 IcecreamFactory 클래스를 상속받은 팩토리 클래스들을 구현해준다.
마지막 클라이언트 코드
[다이어그램]!
여기서 만약에 끌레도르 아이스크림이 추가된다 한다면 Icecream 인터페이스를 구현한 Cledore.java와 IcecreamFactory 추상클래스를 상속받은 CledoreFactory.java를 구현한 후 클라이언트단에 똑같이 구현해주면 된다.