오늘 하루도 어느덧 저물어 가네요
날씨가 더워져서 코로나19로 인한
마스크 착용이 더욱 괴롭게 느껴집니다
하루 빨리 코로나19에 대한
백신이 개발되어 안정되기 바랍니다
아무튼 오늘도 디자인 패턴 학습을 진행하겠습니다
주제는 템플릿 메소드 패턴입니다
템플릿은 잘 아시다시피
일정한 틀, 형식을 의미하는데
이번 패턴은 템플릿의 기능을 가진 패턴입니다
구체적으로는 상위 클래스가 템플릿이되고
하위 클래스에서 구체적인 구현
내용을 결정하는 것입니다
먼저 템플릿 메소드 패턴을 구성하는
역할들을 정리하고 시작하겠습니다
역할 | 설명 |
추상 클래스(Abstract Class) | 템플릿 메소드를 구현 |
구현 클래스(Concrete Class) | 추상 클래스 역할에서 정의되어 있는 추상 메소드를 구체적으로 구현 |
템플릿 메소드 패턴을 구성하는
역할은 비교적 간단하네요~
자 그럼 구현을 해보겠습니다
추상 클래스 역할을 수행하는
AbstractDisplay 클래스를 하나 생성하고
이 클래스를 상속 받는 클래스를 생성합니다
1. 클래스(Class) AbstractDisplay.java
package TemplateMethodPattern; public abstract class AbstractDisplay { public abstract void open(); public abstract void print(); public abstract void close(); public final void display() { open(); for ( int i = 0; i < 5; ++i ) { print(); } close(); } }
2. 클래스(Class) CharDisplay.java
package TemplateMethodPattern; public class CharDisplay extends AbstractDisplay { private char ch; public CharDisplay(char ch) { this.ch = ch; } public void open() { System.out.print("<<"); } public void print() { System.out.print(ch); } public void close() { System.out.println(">>"); } }
3. 클래스(Class) StringDisplay.java
package TemplateMethodPattern; public class StringDisplay extends AbstractDisplay { private String string; private int width; public StringDisplay(String string) { this.string = string; this.width = string.getBytes().length; } public void open() { printLine(); } public void print() { System.out.println("|" + string + "|"); } public void close() { printLine(); } private void printLine() { System.out.print("+"); for ( int i = 0; i < width; ++i ) { System.out.print("-"); } System.out.println("+"); } }
4. 클래스(Class) Test.java
import TemplateMethodPattern.*; public class Test { public static void main(String[] args) { /* Template Method Pattern */ AbstractDisplay displayChar = new CharDisplay('T'); AbstractDisplay displayString = new StringDisplay("Template Method Pattern"); displayChar.display(); displayString.display(); } }
위의 코드를 살펴보면
추상 클래스 AbstractDisplay가
템플릿 메소드 패턴의 추상 클래스 역할로
하위 클래스에서 open(), print(), close()를
구현하도록 하고 있습니다
그리고 display() 메소드에서
세 메소드가 어떻게 동작하는지
알고리즘을 정의하고
이 display() 메소드를
final 키워드를 이용하여 하위 클래스에서
오버라이딩(overriding) 할 수 없게 합니다
Test 클래스에서 실제로 사용할 때는
AbstractDisplay 형 변수에
하위 클래스 객체를 대입하고
단지 display()를 호출합니다
이러면 하위 클래스에서 구현한
open(), print(), close()가
display()에 작성된 순서대로 동작합니다
이렇게 함으로써 상위 클래스인
AbstractDisplay는 하위 클래스에게
구현을 맡기고 자신이 원하는 순서로
프로그램이 동작하도록 하는데 성공합니다
왜 이렇게 작성하는 것일까요?
만약에 CharDisplay와 StringDisplay 클래스를
각각 따로 복사 & 붙여넣기 했고
CharDisplay에서 오류가 발생다면
CharDisplay와 StringDisplay 모두를 수정해야합니다
Concrete Class가 많다면 욕나오겠죠-_-
그런데 이 패턴은 상위 클래스와 하위 클래스가
서로 긴밀하게 작동하고 있습니다
이 얘기는 만약 상위 클래스의 소스를 모른다면
정말 난감한 상황이 발생할 수 있다는 것입니다
여기서 잠깐 참고로 Test 클래스에서
상위 클래스 AbstractDisplay형 변수에
하위 클래스 CharDisplay와 StringDisplay를 대입하는데
이것은 상속의 일반적인 원칙인
LSP(The Liskov Substitution Principle)의 적용입니다
추상 클래스가 등장하면 인터페이스가 생각납니다
그럼 이런 의문이 생길 수 있는데요
이 패턴에 인터페이스를 사용할 수는 없는가?
불가합니다 이유는 display() 메소드에 있는데
인터페이스는 구체적인 구현을 담은
메소드가 있을 수 없기 때문입니다
자바를 학습하면 어쩌면 자연스럽게 알고 있었을 내용이라
이번 주제는 비교적 난이도 낮았던거 같네요
지난 학습이 궁금하시다면 아래의 링크↓↓
2020/06/08 - [Java] - [Design Pattern] 반복자 패턴(Iterator Pattern)
2020/06/09 - [Java] - [Design Pattern] 어댑터 패턴(Adapter Pattern)
아무튼 이것으로 이번 학습을 마치겠습니다
그럼 이만-_-
'Java' 카테고리의 다른 글
[Design Pattern] 빌더 패턴(Builder Pattern) (0) | 2020.06.15 |
---|---|
[Design Pattern] 싱글톤(Singleton) 패턴과 프로토타입(Prototype) 패턴 (0) | 2020.06.14 |
[Design Pattern] 팩토리 메소드 패턴(Factory Method Pattern) (0) | 2020.06.13 |
[Design Pattern] 어댑터 패턴(Adapter Pattern) (0) | 2020.06.09 |
[Design Pattern] 반복자 패턴(Iterator Pattern) (0) | 2020.06.08 |