![템플릿 메서드](/images/patterns/cards/template-method-mini.png?id=9f200248d88026d8e79d0f3dae411ab4)
루비로 작성된 템플릿 메서드
템플릿 메서드는 기초 클래스에서 알고리즘의 골격을 정의할 수 있도록 하는 행동 디자인 패턴입니다. 또 이 패턴은 자식 클래스들이 전체 알고리즘의 구조를 변경하지 않고도 기본 알고리즘의 단계들을 오버라이드할 수 있도록 합니다.
복잡도:
인기도:
사용 사례들: 템플릿 메서드 패턴은 루비 프레임워크들에서 매우 일반적이며 개발자들은 종종 이 패턴을 사용하여 프레임워크 사용자들에게 상속을 사용하여 표준 기능들을 확장하는 간단한 수단을 제공합니다.
식별: 템플릿 메서드는 기초 클래스에 추상적이거나 비어 있는 다른 여러 메서드들을 호출하는 메서드가 있습니다.
개념적인 예시
이 예시는 템플릿 메서드의 구조를 보여주고 다음 질문에 중점을 둡니다:
- 패턴은 어떤 클래스들로 구성되어 있나요?
- 이 클래스들은 어떤 역할을 하나요?
- 패턴의 요소들은 어떻게 서로 연관되어 있나요?
main.rb: 개념적인 예시
# The Abstract Class defines a template method that contains a skeleton of some
# algorithm, composed of calls to (usually) abstract primitive operations.
#
# Concrete subclasses should implement these operations, but leave the template
# method itself intact.
class AbstractClass
# The template method defines the skeleton of an algorithm.
def template_method
base_operation1
required_operations1
base_operation2
hook1
required_operations2
base_operation3
hook2
end
# These operations already have implementations.
def base_operation1
puts 'AbstractClass says: I am doing the bulk of the work'
end
def base_operation2
puts 'AbstractClass says: But I let subclasses override some operations'
end
def base_operation3
puts 'AbstractClass says: But I am doing the bulk of the work anyway'
end
# These operations have to be implemented in subclasses.
def required_operations1
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
# @abstract
def required_operations2
raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
end
# These are "hooks." Subclasses may override them, but it's not mandatory
# since the hooks already have default (but empty) implementation. Hooks
# provide additional extension points in some crucial places of the algorithm.
def hook1; end
def hook2; end
end
# Concrete classes have to implement all abstract operations of the base class.
# They can also override some operations with a default implementation.
class ConcreteClass1 < AbstractClass
def required_operations1
puts 'ConcreteClass1 says: Implemented Operation1'
end
def required_operations2
puts 'ConcreteClass1 says: Implemented Operation2'
end
end
# Usually, concrete classes override only a fraction of base class' operations.
class ConcreteClass2 < AbstractClass
def required_operations1
puts 'ConcreteClass2 says: Implemented Operation1'
end
def required_operations2
puts 'ConcreteClass2 says: Implemented Operation2'
end
def hook1
puts 'ConcreteClass2 says: Overridden Hook1'
end
end
# The client code calls the template method to execute the algorithm. Client
# code does not have to know the concrete class of an object it works with, as
# long as it works with objects through the interface of their base class.
def client_code(abstract_class)
# ...
abstract_class.template_method
# ...
end
puts 'Same client code can work with different subclasses:'
client_code(ConcreteClass1.new)
puts "\n"
puts 'Same client code can work with different subclasses:'
client_code(ConcreteClass2.new)
output.txt: 실행 결과
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass1 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass1 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass2 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass2 says: Overridden Hook1
ConcreteClass2 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway