"행동패턴"의 두 판 사이의 차이
(→상태(State) 패턴) |
(→중재자패턴) |
||
(사용자 2명의 중간 판 15개는 보이지 않습니다) | |||
1번째 줄: | 1번째 줄: | ||
− | ''' | + | '''행동패턴'''<!--행동 패턴-->(behavioral patterns)은 오브젝트 사이의 상호작용과 오브젝트의 역할(책임)에 대한 것이다. '''행위패턴'''<!--행위 패턴-->이라고도 한다.<ref name='be_main'>도킨샤, 〈[https://blog.naver.com/anciid/221763490051 Chapter 1.디자인 패턴 소개 ]〉, 2020-01-07</ref> |
+ | |||
== 종류 == | == 종류 == | ||
− | === | + | === 책임연쇄패턴 === |
− | 여러 개의 객체 중에서 어떤 것이 요구를 처리할 수 있는지를 사전에 알 수 없을 때 사용된다. 즉 요청 처리가 들어오게 되면 그것을 수신하는 객체가 자신이 처리 할 수 없는 경우에는 다음 객체에게 문제를 넘김으로써 최종적으로 요청을 처리 할 수 있는 객체의 의해 처리가 가능하도록 하는 패턴이다. | + | [[책임연쇄패턴]](chain of responsibility)은 여러 개의 객체 중에서 어떤 것이 요구를 처리할 수 있는지를 사전에 알 수 없을 때 사용된다. 즉 요청 처리가 들어오게 되면 그것을 수신하는 객체가 자신이 처리 할 수 없는 경우에는 다음 객체에게 문제를 넘김으로써 최종적으로 요청을 처리 할 수 있는 객체의 의해 처리가 가능하도록 하는 패턴이다. |
− | [[파일:Chain_of.jpg]] | + | |
+ | [[파일:Chain_of.jpg]] | ||
+ | |||
위 그림을 보면 Sender 객체가 Handler 객체에 요청을 하며 그 요청이 수행되는 구조와 일련의 과정들이 나타나 있다.<br> | 위 그림을 보면 Sender 객체가 Handler 객체에 요청을 하며 그 요청이 수행되는 구조와 일련의 과정들이 나타나 있다.<br> | ||
왼쪽의 class diagram을 통해서 Handler 클래스를 상속하고 있는 다른 처리 클래스가 존재한다는 것을 알 수 있고, 오른쪽의 Sequence diagram을 통해서 그 과정이 Handler 클래스를 상속하고 있는 Receiver 1,2,3 클래스의 객체로 이루어진다는 것을 알 수 있다.<br><br> | 왼쪽의 class diagram을 통해서 Handler 클래스를 상속하고 있는 다른 처리 클래스가 존재한다는 것을 알 수 있고, 오른쪽의 Sequence diagram을 통해서 그 과정이 Handler 클래스를 상속하고 있는 Receiver 1,2,3 클래스의 객체로 이루어진다는 것을 알 수 있다.<br><br> | ||
이 패턴은 자바의 Exception Handling과 같은 원리인데 try문으로 코드를 실행시켜서 안되면 이어지는 catch문들이 그것을 처리하고 마지막에 finally가 처리한다는 면에서 비슷하다고 보는 것이다.<ref name='chain'>귤덕, 〈[https://sexycoder.tistory.com/105 Chain of Responsibility Pattern (책임 사슬 패턴) ]〉, 2018-03-02</ref> | 이 패턴은 자바의 Exception Handling과 같은 원리인데 try문으로 코드를 실행시켜서 안되면 이어지는 catch문들이 그것을 처리하고 마지막에 finally가 처리한다는 면에서 비슷하다고 보는 것이다.<ref name='chain'>귤덕, 〈[https://sexycoder.tistory.com/105 Chain of Responsibility Pattern (책임 사슬 패턴) ]〉, 2018-03-02</ref> | ||
− | === | + | === 커맨드패턴=== |
− | + | [[커맨드패턴]](command pattern)은 사용자가 요구하는 명령어를 객체에 캡슐화(encapsulation)하여 저장한다. 각각의 명령어에 해당하는 객체는 그 명령어에 해당하는 기능을 실행하며, 필요에 따라 '명령 취소' 기능을 제공한다. 명령어와 관련된 사항이 객체에 캡슐화되어 있기 때문에, 사용자들은 단순히 그 명령어 객체를 생성해서 사용하기만 하면 된다. 또한, 이러한 명령어 객체들은 모두 공동의 상위 클래스를 갖고 있다. 이 상위 클래스는 각 명령어 객체의 클래스가 구현해야 할 메소드를 정의하고 있다. 예를 들어, 워드 프로세서에서 사용되는 '복사', '잘라내기', '붙여넣기'에 해당하는 명령어 클래스를 각각 CopyCommand, CutCommand, PasteCommand 라고 하고 이 세 클래스가 상속받는 추상 클래스를 AbstractCommand 라고 하면 전체적인 클래스 사이의 관계는 다음 그림과 같을 것이다.<ref name='command'>자바캔, 〈[https://javacan.tistory.com/entry/6 커맨드패턴과 그 구현 ]〉</ref> | |
− | [[파일:command_pattern.gif]] | + | |
+ | [[파일:command_pattern.gif]] | ||
+ | |||
AbstractCommand 클래스는 모든 명령어 클래스가 상속받아야 할 클래스로서 추상 메소드인 execute()와 undo()를 선언하고 있다. 메소드의 이름에서 알 수 있듯이 execute() 메소드는 명령어에 해당하는 기능을 실행하기 위해 호출되는 메소드이며, 따라서 execute#40;) 메소드는 실제 기능을 구현하고 있다. 반면에 undo() 메소드는 '명령 취소'에 해당하는 기능을 제공한다. AbstractCommand 추상 클래스를 상속받는 클래스들은 그 클래스에 알맞도록 execute() 메소드와 undo() 메소드를 구현하면 된다. 예를 들어, CopyCommand 클래스의 execute() 메소드는 사용자가 설정한 블럭에 속한 글자들을 클립보드에 복사할 것이며, undo() 메소드는 클립보드에 저장되어 있는 글자들을 삭제할 것이다.<ref name='command'></ref> | AbstractCommand 클래스는 모든 명령어 클래스가 상속받아야 할 클래스로서 추상 메소드인 execute()와 undo()를 선언하고 있다. 메소드의 이름에서 알 수 있듯이 execute() 메소드는 명령어에 해당하는 기능을 실행하기 위해 호출되는 메소드이며, 따라서 execute#40;) 메소드는 실제 기능을 구현하고 있다. 반면에 undo() 메소드는 '명령 취소'에 해당하는 기능을 제공한다. AbstractCommand 추상 클래스를 상속받는 클래스들은 그 클래스에 알맞도록 execute() 메소드와 undo() 메소드를 구현하면 된다. 예를 들어, CopyCommand 클래스의 execute() 메소드는 사용자가 설정한 블럭에 속한 글자들을 클립보드에 복사할 것이며, undo() 메소드는 클립보드에 저장되어 있는 글자들을 삭제할 것이다.<ref name='command'></ref> | ||
− | 이제 남은 것은 각각의 명령어 객체를 저장하고 관리해주는 관리자 클래스인 CommandManager 클래스가 필요하다. 이 클래스는 실행되는 명령어를 차례대로 저장하고 있으며, 사용자가 '명령취소'를 요청할 경우 가장 최근에 저장된 명령어 객체의 undo() 메소드를 호출해주는 역할을 한다. 즉, 전체적인 클래스 사이의 관계는 다음과 같다. | + | 이제 남은 것은 각각의 명령어 객체를 저장하고 관리해주는 관리자 클래스인 CommandManager 클래스가 필요하다. 이 클래스는 실행되는 명령어를 차례대로 저장하고 있으며, 사용자가 '명령취소'를 요청할 경우 가장 최근에 저장된 명령어 객체의 undo() 메소드를 호출해주는 역할을 한다. 즉, 전체적인 클래스 사이의 관계는 다음과 같다. |
+ | |||
+ | [[파일:command_pattern2.gif]] | ||
+ | |||
여기서 Invoker는 워드프로세서의 경우 사용자가 메뉴를 선택하거나 툴바를 클릭했을 때 발생하는 이벤트를 처리해주는 이벤트 리스너(예를 들어, ActionListener나 ItemListener 등)가 되며, ConcreteCommand 클래스는 CopyCommand와 CutCommand와 같이 실제 명령을 실행(구현)하는 명령어 객체를 나타낸다. CommandManager는 AbstractCommand를 관리하는 클래스이다.<ref name='command'></ref> | 여기서 Invoker는 워드프로세서의 경우 사용자가 메뉴를 선택하거나 툴바를 클릭했을 때 발생하는 이벤트를 처리해주는 이벤트 리스너(예를 들어, ActionListener나 ItemListener 등)가 되며, ConcreteCommand 클래스는 CopyCommand와 CutCommand와 같이 실제 명령을 실행(구현)하는 명령어 객체를 나타낸다. CommandManager는 AbstractCommand를 관리하는 클래스이다.<ref name='command'></ref> | ||
− | === | + | === 인터프리터패턴 === |
− | 문장을 해석할 때 사용하는 패턴이다. 간단한 셸 커맨드 처리, 통신 프로토콜 처리, 수식계산, 도메인 기반 언어(Domain Specific Language - SQL, XML, JSF등)의 해석에 주로 많이 쓰인다. 일반프로그래밍 언어처럼 문장구성이 복잡해지면 사용하지 않는 것이 낫다. | + | [[인터프리터패턴]](interpreter pattern)은 문장을 해석할 때 사용하는 패턴이다. 간단한 셸 커맨드 처리, 통신 프로토콜 처리, 수식계산, 도메인 기반 언어(Domain Specific Language - SQL, XML, JSF등)의 해석에 주로 많이 쓰인다. 일반프로그래밍 언어처럼 문장구성이 복잡해지면 사용하지 않는 것이 낫다. |
− | 중심이 되는 하나의 interprete 메소드에 많은 의무가 달려있기 때문에, 실제적으로 작성하는 코드에서 이 패턴을 사용해 코딩하는 일은 많지 않다. | + | 중심이 되는 하나의 interprete 메소드에 많은 의무가 달려있기 때문에, 실제적으로 작성하는 코드에서 이 패턴을 사용해 코딩하는 일은 많지 않다. |
− | [[파일:interprete_pattern.png]] | + | |
− | + | [[파일:interprete_pattern.png]] | |
+ | |||
+ | 클라이언트는 문장해석의 주체이면서,인터프리터를 문장에 대해 적용한다. | ||
아래 다이어그램을 보면 TerminalExpression과 NonterminalExpression이 존재한다. 트리구조를 생각하면 편하다. 표현식안에 다른 표현식(자식 노드가 있는 경우)에는 다시 평가(Evaluation)을 수행해야 한다. Context는 interpreter(해석기)의 전역정보를 가지고 있다.<ref name='interpreter'>IDEO, 〈[https://m.blog.naver.com/PostView.nhn?blogId=2feelus&logNo=220664898533&proxyReferer=https:%2F%2Fwww.google.com%2F 인터프리터 패턴 - 자바 디자인 패턴과 JDK 예제 ]〉, 2016-03-25</ref> | 아래 다이어그램을 보면 TerminalExpression과 NonterminalExpression이 존재한다. 트리구조를 생각하면 편하다. 표현식안에 다른 표현식(자식 노드가 있는 경우)에는 다시 평가(Evaluation)을 수행해야 한다. Context는 interpreter(해석기)의 전역정보를 가지고 있다.<ref name='interpreter'>IDEO, 〈[https://m.blog.naver.com/PostView.nhn?blogId=2feelus&logNo=220664898533&proxyReferer=https:%2F%2Fwww.google.com%2F 인터프리터 패턴 - 자바 디자인 패턴과 JDK 예제 ]〉, 2016-03-25</ref> | ||
− | === | + | === 반복자패턴 === |
− | 접근기능과 자료구조를 분리시켜서 객체화한다. 서로 다른 구조를 가지고 있는 저장 객체에 대해서 접근하기 위해서 interface를 통일시키고 싶을 때 사용하는 패턴이다. | + | [[반복자패턴]](iterator pattern)은 접근기능과 자료구조를 분리시켜서 객체화한다. 서로 다른 구조를 가지고 있는 저장 객체에 대해서 접근하기 위해서 interface를 통일시키고 싶을 때 사용하는 패턴이다. |
− | [[파일:iterator_pattern.png]] | + | |
+ | [[파일:iterator_pattern.png]] | ||
+ | |||
* Iterator : 집합체의 요소들을 순서대로 검색하기 위한 인터페이스 정의 | * Iterator : 집합체의 요소들을 순서대로 검색하기 위한 인터페이스 정의 | ||
* ConcreateIterator : Iterator 인터페이스를 구현함 | * ConcreateIterator : Iterator 인터페이스를 구현함 | ||
− | * Aggregate : 여러 요소들로 이루어져 있는 집합체 | + | * Aggregate : 여러 요소들로 이루어져 있는 집합체<ref name='iterator'>Lkt_Programmer, 〈[https://lktprogrammer.tistory.com/40 08 반복자 패턴(Iterator Pattern) ]〉, 2017-09-24</ref> |
− | <ref name='iterator'>Lkt_Programmer, 〈[https://lktprogrammer.tistory.com/40 08 반복자 패턴(Iterator Pattern) ]〉, 2017-09-24</ref> | + | |
+ | === 중재자패턴 === | ||
+ | [[중재자패턴]](mediator pattern)은 한 집합에 속해있는 객체들의 상호 작용을 캡슐화하는 객체를 정의하는 패턴이다. 중재자는 객체들이 직접 서로 참조하지 않도록 함으로써 객체들 간의 느슨한 연결을 촉진시키며 객체들의 상호작용을 독립적으로 다양화시킬 수 있도록 해준다. | ||
− | |||
− | |||
[[파일:mediator_pattern.png]] | [[파일:mediator_pattern.png]] | ||
− | + | ||
* Mediator는 Colleague가 Mediator에서 알려주는 것을 의미하고, ColleagueA도 마찬가지로 Mediator가 ColleagueA, B에게 알리는 것을 의미한다.<ref name='mediator'>Crocus, 〈[https://www.crocus.co.kr/1542 08 중재자 패턴(Mediator Pattern) ]〉, 2019-07-07</ref> | * Mediator는 Colleague가 Mediator에서 알려주는 것을 의미하고, ColleagueA도 마찬가지로 Mediator가 ColleagueA, B에게 알리는 것을 의미한다.<ref name='mediator'>Crocus, 〈[https://www.crocus.co.kr/1542 08 중재자 패턴(Mediator Pattern) ]〉, 2019-07-07</ref> | ||
− | === | + | === 옵저버패턴 === |
− | 객체들 사이에 1 : N 의 의존관계를 정의하여 어떤 객체의 상태가 변할 때, 의존관계에 있는 모든 객체들이 통지받고 자동으로 갱신될 수 있게 만드는 패턴이다. | + | [[옵저버패턴]](observer pattern)은 객체들 사이에 1 : N 의 의존관계를 정의하여 어떤 객체의 상태가 변할 때, 의존관계에 있는 모든 객체들이 통지받고 자동으로 갱신될 수 있게 만드는 패턴이다. |
− | [[파일:observer_pattern.jpg]] | + | |
− | Publisher를 구현한 NewsMachine 클래스는 정보를 제공하는 Publisher가 되며 Observer객체들을 가지고 있다. 그리고 Observer 인터페이스를 구현한 AnnualSubscriber(매년 정기구독자), EventSubscriber(이벤트 고객) 클래스는 NewsMachine이 새로운 뉴스를 notifyObserver() 를 호출하면서 알려줄 때마다 Update가 호출된다.<ref name=' | + | [[파일:observer_pattern.jpg]] |
+ | |||
+ | Publisher를 구현한 NewsMachine 클래스는 정보를 제공하는 Publisher가 되며 Observer객체들을 가지고 있다. 그리고 Observer 인터페이스를 구현한 AnnualSubscriber(매년 정기구독자), EventSubscriber(이벤트 고객) 클래스는 NewsMachine이 새로운 뉴스를 notifyObserver() 를 호출하면서 알려줄 때마다 Update가 호출된다.<ref name='observer'>JAMINS, 〈[https://flowarc.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%98%B5%EC%A0%80%EB%B2%84-%ED%8C%A8%ED%84%B4Observer-Pattern 08 디자인 패턴 - 옵저버 패턴 ]〉, 2016-01-25</ref> | ||
+ | |||
+ | === 상태패턴 === | ||
+ | [[상태패턴]](state pattern)은 객체 내부의 상태에 따라 동작을 변경해야할 때 사용하는 디자인 패턴이다. 하나의 객체에 대한 여러 동작을 구현해야할 때 상태 객체만 수정하므로 동작의 추가, 삭제 및 수정이 간단해지고 객체의 상태에 따른 조건문(if/else, switch)이 줄어들어 코드가 간결해지고 가독성이 올라간다는 장점이 있다. | ||
+ | |||
+ | [[파일:state_pattern.png]] | ||
− | |||
− | |||
− | |||
* Context : 객체의 상태를 정의하는 데 사용되는 메소드를 정의하는 인터페이스이다. | * Context : 객체의 상태를 정의하는 데 사용되는 메소드를 정의하는 인터페이스이다. | ||
* State : 상태에 따른 동작을 정의하는 인터페이스이다. | * State : 상태에 따른 동작을 정의하는 인터페이스이다. | ||
− | * ConcreteState : State에서 정의된 메소드를 구현하는 클래스이다. | + | * ConcreteState : State에서 정의된 메소드를 구현하는 클래스이다.<ref name='state'>TevQabs, 〈[https://always-intern.tistory.com/9 08 디자인 패턴 - 상태 패턴(State Pattern) ]〉, 2019-02-15</ref> |
+ | |||
+ | === 전략패턴 === | ||
+ | [[전략패턴]](strategy pattern)은 동일 계열의 알고리즘들을 정의하고 각각 캡슐화하며 이들을 상호교환 가능하도록 만드는 것이다. 알고리즘을 사용하는 사용자로부터 독립적으로 알고리즘이 변경될 수 있도록 하는 패턴이다. | ||
+ | |||
+ | [[파일:strategy_pattern.jpg]] | ||
+ | |||
+ | 전체 설계를 하면 위와 같이 된다. 일단 로직으로는 미사일 쏘는 부분과 폭탄을 쏘는 부분 크게 두 가지이므로 각각 [[캡슐화]]한다. 인터페이스로 ShootAction, BombAction 을 선언하여 형태를 만든다. 그 다음 미사일 쏘는 부분에서 직선과 유도탄 형식 두가지의 로직이 나오는데 이것들을 전부 ShootAction 인터페이스로 연결한다. | ||
+ | |||
+ | 다음에 새로운 미사일의 형태, 예를 들면 Y 자로 퍼지는 미사일을 추가하고 싶을때 ShootAction 인터페이스에 연결한 새로운 Class를 생성하여 로직을 작성하면 된다. | ||
+ | |||
+ | 폭탄도 마찬가지로 BombAction 인터페이스를 만들어놓고 SpreadBomb와 NoBomb를 만든다. NoBomb는 폭탄이 없다는 뜻의 클래스이다. bomb() 내부에는 아무 내용도 존재하지 않는다. | ||
− | + | 이렇게 다양한 로직들을 적용하기 위해 유닛부분을 손 봐야 한다. 유닛종류에는 전투기, 헬리콥터 두 종류인데 이 상위 추상클래스인 Unit 을 선언한다. Unit에는 display 와 같이 유닛을 그리는 공통적인 메소드가 들어있고, 각각 유닛에 맞는 미사일과 폭탄을 선언하기 위해 인터페이스 형식의 variable 을 선언한다. | |
− | |||
− | + | 실질적으로 Unit 클래스를 상속받은 전투기(Fighter) 클래스와 헬리콥터(Helicopter) 클래스에서는 생성자에 각각에 맞는 미사일과 폭탄을 정의하면 된다.<ref name='strategy_pattern'>JAMINS,〈[https://flowarc.tistory.com/entry/1-Strategy-Pattern 디자인패턴 - 스트레티지 패턴(Strategy Pattern)]〉, 2015-07-09</ref> | |
− | |||
− | === | + | === 템플릿메소드패턴 === |
− | + | [[템플릿메소드패턴]](template method pattern)은 객체의 연산에서 [[알고리즘]]의 뼈대만 정의하고, 나머지는 서브클래스에서 이루어지게 하는 패턴이다. 템플릿 패턴은 알고리즘의 구조는 변경하지 않고 알고리즘의 각 단계를 서브클래스에서 재정의하게 된다.<br> | |
+ | [[파일:template_method_pattern.png]] | ||
+ | * AbstractClass | ||
+ | :ConcreteClass 가 상속받아야 할 추상 클래스이다. | ||
+ | :templateMethod() 에 클라이언트가 사용할 로직을 담는다. | ||
+ | :각 로직의 요소는 method1(), method2() 에 담기며, 이는 ConcreteClass 에서 구현한다. | ||
+ | * ConcreteClass | ||
+ | :AbstractClass 를 상속받아 필요한 로직 요소 method() 를 필요에 맞게 구현한다. | ||
+ | <ref name='template_pattern'>흠시,〈[https://dailyheumsi.tistory.com/210 행동 패턴, 템플릿메쏘드(Template method)]〉, 2020-03-21</ref> | ||
+ | === 비지터패턴 === | ||
+ | [[비지터패턴]](visitor pattern)은 객체구조를 이루는 원소에 대해 수행할 연산을 표현한다. 방문자는 연산에 적용할 원소의 클래스를 변경하지 않고 새로운 연산을 재정의할 수 있다.<br> | ||
+ | [[파일:visitor_pattern.jpg]] | ||
+ | * Visitor | ||
+ | :방문자 클래스의 인터페이스이다. | ||
+ | :visit(Element)을 공용 인터페이스로 쓴다. Element는 방문 공간이다. | ||
+ | * Element | ||
+ | :방문 공간 클래스의 인터페이스이다. | ||
+ | :accept(Vistor)를 공용 인터페이스로 쓴다. Visitor는 방문자다. | ||
+ | :내부적으로 Vistor.visit(this)를 호출한다. | ||
+ | * ConcreteVisitor | ||
+ | :Visitor를 구체적으로 구현한 클래스이다. | ||
+ | * ConcreteElement | ||
+ | :Element를 구체적으로 구현한 클래스이다. | ||
+ | <ref name='visitor_pattern'>흠시,〈[https://dailyheumsi.tistory.com/216 행동 패턴, 방문자(Visitor)]〉, 2020-04-11</ref> | ||
{{각주}} | {{각주}} | ||
== 참고자료 == | == 참고자료 == | ||
− | * | + | * 도킨샤, 〈[https://blog.naver.com/anciid/221763490051 Chapter 1.디자인 패턴 소개 ]〉, 2020-01-07 |
+ | * 귤덕, 〈[https://sexycoder.tistory.com/105 Chain of Responsibility Pattern (책임 사슬 패턴) ]〉, 2018-03-02 | ||
+ | * 자바캔, 〈[https://javacan.tistory.com/entry/6 커맨드패턴과 그 구현 ]〉 | ||
+ | * IDEO, 〈[https://m.blog.naver.com/PostView.nhn?blogId=2feelus&logNo=220664898533&proxyReferer=https:%2F%2Fwww.google.com%2F 인터프리터 패턴 - 자바 디자인 패턴과 JDK 예제 ]〉, 2016-03-25 | ||
+ | * Lkt_Programmer, 〈[https://lktprogrammer.tistory.com/40 08 반복자 패턴(Iterator Pattern) ]〉, 2017-09-24 | ||
+ | * Crocus, 〈[https://www.crocus.co.kr/1542 08 중재자 패턴(Mediator Pattern) ]〉, 2019-07-07 | ||
+ | * JAMINS, 〈[https://flowarc.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%98%B5%EC%A0%80%EB%B2%84-%ED%8C%A8%ED%84%B4Observer-Pattern 08 디자인 패턴 - 옵저버 패턴 ]〉, 2016-01-25 | ||
+ | * TevQabs, 〈[https://always-intern.tistory.com/9 08 디자인 패턴 - 상태 패턴(State Pattern) ]〉, 2019-02-15 | ||
+ | * JAMINS,〈[https://flowarc.tistory.com/entry/1-Strategy-Pattern 디자인패턴 - 스트레티지 패턴(Strategy Pattern)]〉, 2015-07-09 | ||
+ | * 흠시,〈[https://dailyheumsi.tistory.com/210 행동 패턴, 템플릿메쏘드(Template method)]〉, 2020-03-21 | ||
+ | * 흠시,〈[https://dailyheumsi.tistory.com/216 행동 패턴, 방문자(Visitor)]〉, 2020-04-11 | ||
+ | |||
== 같이 보기 == | == 같이 보기 == | ||
− | * | + | * [[디자인패턴]] |
+ | |||
{{프로그래밍|검토 필요}} | {{프로그래밍|검토 필요}} |
2020년 8월 18일 (화) 14:44 기준 최신판
행동패턴(behavioral patterns)은 오브젝트 사이의 상호작용과 오브젝트의 역할(책임)에 대한 것이다. 행위패턴이라고도 한다.[1]
목차
종류[편집]
책임연쇄패턴[편집]
책임연쇄패턴(chain of responsibility)은 여러 개의 객체 중에서 어떤 것이 요구를 처리할 수 있는지를 사전에 알 수 없을 때 사용된다. 즉 요청 처리가 들어오게 되면 그것을 수신하는 객체가 자신이 처리 할 수 없는 경우에는 다음 객체에게 문제를 넘김으로써 최종적으로 요청을 처리 할 수 있는 객체의 의해 처리가 가능하도록 하는 패턴이다.
위 그림을 보면 Sender 객체가 Handler 객체에 요청을 하며 그 요청이 수행되는 구조와 일련의 과정들이 나타나 있다.
왼쪽의 class diagram을 통해서 Handler 클래스를 상속하고 있는 다른 처리 클래스가 존재한다는 것을 알 수 있고, 오른쪽의 Sequence diagram을 통해서 그 과정이 Handler 클래스를 상속하고 있는 Receiver 1,2,3 클래스의 객체로 이루어진다는 것을 알 수 있다.
이 패턴은 자바의 Exception Handling과 같은 원리인데 try문으로 코드를 실행시켜서 안되면 이어지는 catch문들이 그것을 처리하고 마지막에 finally가 처리한다는 면에서 비슷하다고 보는 것이다.[2]
커맨드패턴[편집]
커맨드패턴(command pattern)은 사용자가 요구하는 명령어를 객체에 캡슐화(encapsulation)하여 저장한다. 각각의 명령어에 해당하는 객체는 그 명령어에 해당하는 기능을 실행하며, 필요에 따라 '명령 취소' 기능을 제공한다. 명령어와 관련된 사항이 객체에 캡슐화되어 있기 때문에, 사용자들은 단순히 그 명령어 객체를 생성해서 사용하기만 하면 된다. 또한, 이러한 명령어 객체들은 모두 공동의 상위 클래스를 갖고 있다. 이 상위 클래스는 각 명령어 객체의 클래스가 구현해야 할 메소드를 정의하고 있다. 예를 들어, 워드 프로세서에서 사용되는 '복사', '잘라내기', '붙여넣기'에 해당하는 명령어 클래스를 각각 CopyCommand, CutCommand, PasteCommand 라고 하고 이 세 클래스가 상속받는 추상 클래스를 AbstractCommand 라고 하면 전체적인 클래스 사이의 관계는 다음 그림과 같을 것이다.[3]
AbstractCommand 클래스는 모든 명령어 클래스가 상속받아야 할 클래스로서 추상 메소드인 execute()와 undo()를 선언하고 있다. 메소드의 이름에서 알 수 있듯이 execute() 메소드는 명령어에 해당하는 기능을 실행하기 위해 호출되는 메소드이며, 따라서 execute#40;) 메소드는 실제 기능을 구현하고 있다. 반면에 undo() 메소드는 '명령 취소'에 해당하는 기능을 제공한다. AbstractCommand 추상 클래스를 상속받는 클래스들은 그 클래스에 알맞도록 execute() 메소드와 undo() 메소드를 구현하면 된다. 예를 들어, CopyCommand 클래스의 execute() 메소드는 사용자가 설정한 블럭에 속한 글자들을 클립보드에 복사할 것이며, undo() 메소드는 클립보드에 저장되어 있는 글자들을 삭제할 것이다.[3]
이제 남은 것은 각각의 명령어 객체를 저장하고 관리해주는 관리자 클래스인 CommandManager 클래스가 필요하다. 이 클래스는 실행되는 명령어를 차례대로 저장하고 있으며, 사용자가 '명령취소'를 요청할 경우 가장 최근에 저장된 명령어 객체의 undo() 메소드를 호출해주는 역할을 한다. 즉, 전체적인 클래스 사이의 관계는 다음과 같다.
여기서 Invoker는 워드프로세서의 경우 사용자가 메뉴를 선택하거나 툴바를 클릭했을 때 발생하는 이벤트를 처리해주는 이벤트 리스너(예를 들어, ActionListener나 ItemListener 등)가 되며, ConcreteCommand 클래스는 CopyCommand와 CutCommand와 같이 실제 명령을 실행(구현)하는 명령어 객체를 나타낸다. CommandManager는 AbstractCommand를 관리하는 클래스이다.[3]
인터프리터패턴[편집]
인터프리터패턴(interpreter pattern)은 문장을 해석할 때 사용하는 패턴이다. 간단한 셸 커맨드 처리, 통신 프로토콜 처리, 수식계산, 도메인 기반 언어(Domain Specific Language - SQL, XML, JSF등)의 해석에 주로 많이 쓰인다. 일반프로그래밍 언어처럼 문장구성이 복잡해지면 사용하지 않는 것이 낫다. 중심이 되는 하나의 interprete 메소드에 많은 의무가 달려있기 때문에, 실제적으로 작성하는 코드에서 이 패턴을 사용해 코딩하는 일은 많지 않다.
클라이언트는 문장해석의 주체이면서,인터프리터를 문장에 대해 적용한다. 아래 다이어그램을 보면 TerminalExpression과 NonterminalExpression이 존재한다. 트리구조를 생각하면 편하다. 표현식안에 다른 표현식(자식 노드가 있는 경우)에는 다시 평가(Evaluation)을 수행해야 한다. Context는 interpreter(해석기)의 전역정보를 가지고 있다.[4]
반복자패턴[편집]
반복자패턴(iterator pattern)은 접근기능과 자료구조를 분리시켜서 객체화한다. 서로 다른 구조를 가지고 있는 저장 객체에 대해서 접근하기 위해서 interface를 통일시키고 싶을 때 사용하는 패턴이다.
- Iterator : 집합체의 요소들을 순서대로 검색하기 위한 인터페이스 정의
- ConcreateIterator : Iterator 인터페이스를 구현함
- Aggregate : 여러 요소들로 이루어져 있는 집합체[5]
중재자패턴[편집]
중재자패턴(mediator pattern)은 한 집합에 속해있는 객체들의 상호 작용을 캡슐화하는 객체를 정의하는 패턴이다. 중재자는 객체들이 직접 서로 참조하지 않도록 함으로써 객체들 간의 느슨한 연결을 촉진시키며 객체들의 상호작용을 독립적으로 다양화시킬 수 있도록 해준다.
- Mediator는 Colleague가 Mediator에서 알려주는 것을 의미하고, ColleagueA도 마찬가지로 Mediator가 ColleagueA, B에게 알리는 것을 의미한다.[6]
옵저버패턴[편집]
옵저버패턴(observer pattern)은 객체들 사이에 1 : N 의 의존관계를 정의하여 어떤 객체의 상태가 변할 때, 의존관계에 있는 모든 객체들이 통지받고 자동으로 갱신될 수 있게 만드는 패턴이다.
Publisher를 구현한 NewsMachine 클래스는 정보를 제공하는 Publisher가 되며 Observer객체들을 가지고 있다. 그리고 Observer 인터페이스를 구현한 AnnualSubscriber(매년 정기구독자), EventSubscriber(이벤트 고객) 클래스는 NewsMachine이 새로운 뉴스를 notifyObserver() 를 호출하면서 알려줄 때마다 Update가 호출된다.[7]
상태패턴[편집]
상태패턴(state pattern)은 객체 내부의 상태에 따라 동작을 변경해야할 때 사용하는 디자인 패턴이다. 하나의 객체에 대한 여러 동작을 구현해야할 때 상태 객체만 수정하므로 동작의 추가, 삭제 및 수정이 간단해지고 객체의 상태에 따른 조건문(if/else, switch)이 줄어들어 코드가 간결해지고 가독성이 올라간다는 장점이 있다.
- Context : 객체의 상태를 정의하는 데 사용되는 메소드를 정의하는 인터페이스이다.
- State : 상태에 따른 동작을 정의하는 인터페이스이다.
- ConcreteState : State에서 정의된 메소드를 구현하는 클래스이다.[8]
전략패턴[편집]
전략패턴(strategy pattern)은 동일 계열의 알고리즘들을 정의하고 각각 캡슐화하며 이들을 상호교환 가능하도록 만드는 것이다. 알고리즘을 사용하는 사용자로부터 독립적으로 알고리즘이 변경될 수 있도록 하는 패턴이다.
전체 설계를 하면 위와 같이 된다. 일단 로직으로는 미사일 쏘는 부분과 폭탄을 쏘는 부분 크게 두 가지이므로 각각 캡슐화한다. 인터페이스로 ShootAction, BombAction 을 선언하여 형태를 만든다. 그 다음 미사일 쏘는 부분에서 직선과 유도탄 형식 두가지의 로직이 나오는데 이것들을 전부 ShootAction 인터페이스로 연결한다.
다음에 새로운 미사일의 형태, 예를 들면 Y 자로 퍼지는 미사일을 추가하고 싶을때 ShootAction 인터페이스에 연결한 새로운 Class를 생성하여 로직을 작성하면 된다.
폭탄도 마찬가지로 BombAction 인터페이스를 만들어놓고 SpreadBomb와 NoBomb를 만든다. NoBomb는 폭탄이 없다는 뜻의 클래스이다. bomb() 내부에는 아무 내용도 존재하지 않는다.
이렇게 다양한 로직들을 적용하기 위해 유닛부분을 손 봐야 한다. 유닛종류에는 전투기, 헬리콥터 두 종류인데 이 상위 추상클래스인 Unit 을 선언한다. Unit에는 display 와 같이 유닛을 그리는 공통적인 메소드가 들어있고, 각각 유닛에 맞는 미사일과 폭탄을 선언하기 위해 인터페이스 형식의 variable 을 선언한다.
실질적으로 Unit 클래스를 상속받은 전투기(Fighter) 클래스와 헬리콥터(Helicopter) 클래스에서는 생성자에 각각에 맞는 미사일과 폭탄을 정의하면 된다.[9]
템플릿메소드패턴[편집]
템플릿메소드패턴(template method pattern)은 객체의 연산에서 알고리즘의 뼈대만 정의하고, 나머지는 서브클래스에서 이루어지게 하는 패턴이다. 템플릿 패턴은 알고리즘의 구조는 변경하지 않고 알고리즘의 각 단계를 서브클래스에서 재정의하게 된다.
- AbstractClass
- ConcreteClass 가 상속받아야 할 추상 클래스이다.
- templateMethod() 에 클라이언트가 사용할 로직을 담는다.
- 각 로직의 요소는 method1(), method2() 에 담기며, 이는 ConcreteClass 에서 구현한다.
- ConcreteClass
- AbstractClass 를 상속받아 필요한 로직 요소 method() 를 필요에 맞게 구현한다.
비지터패턴[편집]
비지터패턴(visitor pattern)은 객체구조를 이루는 원소에 대해 수행할 연산을 표현한다. 방문자는 연산에 적용할 원소의 클래스를 변경하지 않고 새로운 연산을 재정의할 수 있다.
- Visitor
- 방문자 클래스의 인터페이스이다.
- visit(Element)을 공용 인터페이스로 쓴다. Element는 방문 공간이다.
- Element
- 방문 공간 클래스의 인터페이스이다.
- accept(Vistor)를 공용 인터페이스로 쓴다. Visitor는 방문자다.
- 내부적으로 Vistor.visit(this)를 호출한다.
- ConcreteVisitor
- Visitor를 구체적으로 구현한 클래스이다.
- ConcreteElement
- Element를 구체적으로 구현한 클래스이다.
각주[편집]
- ↑ 도킨샤, 〈Chapter 1.디자인 패턴 소개 〉, 2020-01-07
- ↑ 귤덕, 〈Chain of Responsibility Pattern (책임 사슬 패턴) 〉, 2018-03-02
- ↑ 3.0 3.1 3.2 자바캔, 〈커맨드패턴과 그 구현 〉
- ↑ IDEO, 〈인터프리터 패턴 - 자바 디자인 패턴과 JDK 예제 〉, 2016-03-25
- ↑ Lkt_Programmer, 〈08 반복자 패턴(Iterator Pattern) 〉, 2017-09-24
- ↑ Crocus, 〈08 중재자 패턴(Mediator Pattern) 〉, 2019-07-07
- ↑ JAMINS, 〈08 디자인 패턴 - 옵저버 패턴 〉, 2016-01-25
- ↑ TevQabs, 〈08 디자인 패턴 - 상태 패턴(State Pattern) 〉, 2019-02-15
- ↑ JAMINS,〈디자인패턴 - 스트레티지 패턴(Strategy Pattern)〉, 2015-07-09
- ↑ 흠시,〈행동 패턴, 템플릿메쏘드(Template method)〉, 2020-03-21
- ↑ 흠시,〈행동 패턴, 방문자(Visitor)〉, 2020-04-11
참고자료[편집]
- 도킨샤, 〈Chapter 1.디자인 패턴 소개 〉, 2020-01-07
- 귤덕, 〈Chain of Responsibility Pattern (책임 사슬 패턴) 〉, 2018-03-02
- 자바캔, 〈커맨드패턴과 그 구현 〉
- IDEO, 〈인터프리터 패턴 - 자바 디자인 패턴과 JDK 예제 〉, 2016-03-25
- Lkt_Programmer, 〈08 반복자 패턴(Iterator Pattern) 〉, 2017-09-24
- Crocus, 〈08 중재자 패턴(Mediator Pattern) 〉, 2019-07-07
- JAMINS, 〈08 디자인 패턴 - 옵저버 패턴 〉, 2016-01-25
- TevQabs, 〈08 디자인 패턴 - 상태 패턴(State Pattern) 〉, 2019-02-15
- JAMINS,〈디자인패턴 - 스트레티지 패턴(Strategy Pattern)〉, 2015-07-09
- 흠시,〈행동 패턴, 템플릿메쏘드(Template method)〉, 2020-03-21
- 흠시,〈행동 패턴, 방문자(Visitor)〉, 2020-04-11
같이 보기[편집]