디자인 패턴 - 스테이트 패턴(State pattern)

정의 : 객체의 내부 상태가 바뀜에 따라서 객체의 행동을 바꿀 수 있다. 마치 객체의 클래스가 바뀌는 것과 같은 결과를 얻을 수 있다.  스테이트 객체로 일련의 행동을 캡슐화하고 이를 컨텍스트 객체에서 상태에 따라 갈아낀다. 그러면 컨텍스트 객체는 자신의 상태에 따라 스테이트 객체의 행동을 하게 된다.  상태를 기반으로 하는 행동을 캡슐화하고, 행동을 현재 상태한테 위임한다. 상태 전환은 스테이트 클래스에서 제어할 수도 있고, 컨텍스트 클래스에서 제어할 수도 있다.  스트래티지 패턴과 같은 방식으로 행동을 상속해서 사용한다. 스테이트 패턴은 상황에 따라 컨텍스트(Context) 객체에서 여러 스테이트 객체 중 하나가 내부 상태를 나타내고, 이 스테이트 객체에 따라 컨텍스트 객체의 행동도 자연스럽게 바뀐다. 클라이언트는 상태 객체에 대해 몰라도 상관 없다.  이 점에서 스트래티지 패턴과의 차이가 있다. 스트래티지 패턴을 사용할 때에는 클라이언트에서 컨텍스트 객체에게 어떤 전략(Stratege) 객체를 사용할지를 지정해준다. 일반적으로 스트래티지 패턴은 서브클래스를 만드는 대신 행동을 상속하여 유연성을 극대화시키기 위해 쓰인다. 스트래티지 패턴을 사용하면 구성을 통해 행동을 정의하는 객체를 유연하게 바꿀 수 있다.  바꿔 쓸 수 있는 행동을 캡슐화한 다음, 실제 행동은 다른 객체에 위임한다. 스테이트 패턴은 상태 객체를 바꾸는 것만으로 컨텍스트 객체의 행동을 바꿀 수 있다. 애니메이션 상태 제어, 유닛의 상태변경(공격<->대기<->이동 등) 등에 쓰일 수 있다. 유한 상태 기계(FSM) 을 구현하는 좋은 방법이다. 예시: State { Handle ( ) } IdleState : State { Handle ( ) { IdleAnimation . Play } MoveState : State { Handle ( ) { MoveAnimation . Pl...

디자인 패턴 - 컴포지트 패턴(Composite pattern)

정의 : 객체들을 트리 구조로 구성하여 부분과 전체를 나타내는 계층구조로 만드는 것.  클라이언트에서 개별 객체와 다른 객체들로 구성된 복합 객체를 똑같은 방법으로 다룰 수 있다. 개별 객체와 다른 개별객체들을 포함하는 복합 객체를 구분할 필요 없이 똑같은 작업이 가능하다.  예를 들어 파일시스템의 트리 구조. GUI 시스템의 캔버스-패널-버튼-텍스트 등의 트리 구조.  부분-전체 관계를 가진 객체 컬렉션이 있으며, 이 객체들을 모두 똑같은 방식으로 다루고 싶을 때 사용한다.  Component 인터페이스는 자신의 구성요소로서의 역할을 수행하는 메소드인 Operation과, 자신의 하위에 다른 Component를 추가/삭제하거나 조회하는 메소드를 제공한다.  컴포넌트 인터페이스를 만들고, 이를 복합(Composite) 객체와 리프 객체에서 모두 구현한다. 각자 용도에 맞는 메소드만 구현하고, 그 외 쓸모없는 메소드는 기본 메소드를 그대로 쓸 수 있도록 한다. 컴포넌트는 각기 자신의 Operation을 구현한다. 추가로 자식 컴포넌트를 관리하는 메소드를 구현할 수도 있다.  리프 노드는 자식이 0개인 복합 객체로 볼 수 있으며 사실상 자식이 없기 때문에 굳이 자신의 하위 컴포넌트를 관리하는 메소드를 오버라이드해서 구현하지 않고 기본 메소드를 쓰는 것이라 볼 수 있다.  복합객체의 Operation 자신의 할 일 뿐 아니라 자신이 가지고 있는 개별객체들의 Operation을 재귀적으로 호출한다. 이로써 최상위 객체의 Operation를 실행한다면 트리 구조로 가지고 있는 모든 자식 객체들의 Operation이 계층적으로 실행된다.  컴포지트 패턴은 단일 역할 원칙을 깨는 대신 투명성을 확보한다. 클라이언트에서는, 컴포넌트 인터페이스를 구현하는 객체가 개별 리프 노드인지 최상위 복합 노드인지를 구분하지 않고 똑같은 방식으로 처리할 수 있다. 클라이언트를 단순화할 수 있는...

디자인 패턴 - 이터레이터 패턴(Iterator pattern)

정의 : 컬렉션 구현 방법을 노출시키지 않으면서도 그 집합체 안에 들어있는 모든 항목에 접근할 수 있게 해 주는 방법을 제공하는 패턴 객체의 컬렉션에 대한 반복작업을 처리하는 방법을 캡슐화. 이터레이터 인터페이스를 정의해두고, 콜렉션에서는 이 인터페이스를 구현. 클라이언트에서는 이터레이터를 이용해 어떤 컬렉션이든 같은 방식으로 사용 가능. HasNext ( ), MoveNext ( ) 이터레이터는 기본적으로 위의 두 메소드를 구현해둔다. 보통 이터레이터를 컬렉션으로부터 얻었을 때, 이터레이터는 첫 번째 항목이 아니라 그 이전을 가리키고 있다. 즉, MoveNext()를 최초 한 번 수행해서 얻는 값이 컬렉션의 첫번째 값. 예시: SomeCollection :  Itrerator Client . main ( ) { Iterator iter = SomeCollection . GetIterator ( ); iter . Next ( ); ]

디자인 패턴 - 템플릿 메소드 패턴(Template method pattern)

템플릿 메소드 패턴 정의 : 메소드에서 알고리즘의 골격을 정의한다. 알고리즘의 여러 단계 중 일부는 서브클래스에서 구현할 수 있다.   알고리즘의 각 단계들을 정의하며, 그 중 한 개 이상의 단계가 서브클래스에 의해 제공될 수 있다. 템플릿 메소드를 이용하면 알고리즘의 구조는 그대로 유지하면서 서브클래스에서 특정 단계를 재정의할 수 있다.  여러 단계 가운데 하나 이상이 추상 메소드로 정의되며, 그 추상 메소드는 서브클래스에서 구현된다. 서브클래스에서 일부분을 구현할 수 있도록 하면서도 알고리즘의 구조는 바꾸지 않아도 된다.  후크(Hook)를 구현할 수 있다. 추상 클래스에서 선언되는 메소드지만 기본적인 내용만, 혹은 아무 내용도 들어있지 않은 메소드다. 이를 이용하면 서브클래스 입장에서는 다양한 위치에서 알고리즘에 끼어들 수 있다.  알고리즘의 특정 부분이 선택적으로 적용되어야 하는 경우에 후크를 오버라이드해서 쓸 수 있다. 예시 : AbstractClass {      TemplateMethod ( ) { Primitive1 ( ); Primitive2 ( ); ConcreteOp ( ); if ( Hook ( ) ) something; } }    ConcreteClass : AbstractClass {     override Primitive1 ( ); override Primitive2 ( ); override Hook ( ); } Client . ConcreteClass . TemplateMethod ( );

디자인 패턴 - 퍼사드 패턴(Facade pattern)

퍼사드 패턴 정의 : 어떤 서브시스템의 일련의 인터페이스에 대한 통합된 인터페이스를 제공한다. 고수준 인터페이스를 정의한다. 클라이언트를 복잡한 서브시스템과 분리시켜주는 역할을 한다. 구성을 통해 퍼사드에서 서브시스템에 있는 모든 구성요소에 접근할 수 있게끔 한다. 퍼사드 클래스는 서브시스템 클래스들을 캡슐화하지 않는다. 그냥 서브시스템 클래스의 기능을 사용할 수 있는 간단한 인터페이스만 제공한다. 어댑터 패턴은  인터페이스를 변경 해서 클라이언트에서 필요로 하는 인터페이스로 적응시키기 위한 용도. 퍼사드 패턴은 어떤 서브시스템에 대한 간단한 인터페이스를 제공. 예시: SubSystemOne , SubSystemTwo, SubSystemThree AFacade{ DoSomething(){ SubSystemOne.Do1(); SubSystemTwo.Do2(); SubSystemThree.Do3(); } Client . AFacade . DoSomething ( ); // All subsystem of facade do their job.

디자인 패턴 - 어댑터 패턴(Adapter pattern)

어댑터 패턴 정의 : 한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환해주는 패턴. 호환되지 않는 인터페이스를 그대로 활용 가능. 클라이언트와 구현된 인터페이스 분리 가능. 클라이언트(Client), 어댑터(Adapter), 어댑티(Adaptee). 클라이언트에서 타겟 인터페이스를 사용하여 메소드를 호출함으로써 어댑터에 요청 어댑터에서는 어댑티 인터페이스를 사용하여 그 요청을 어댑티에 대한 메소드 호출로 변환 클라이언트에서는 호출 결과를 받긴 하지만 중간에 어댑터가 껴 있는지는 알 수 없음 예시: Target { Request ( ) } Adapter : Target { Request ( ) { Adaptee . SpecificRequest ( ) } } Client . Target . Request ( ) ; //Adaptee . SpecificRequest ( ) executed.

디자인 패턴 - 커맨드 패턴(Command pattern)

이미지
정의 : 요청을 객체 형태 캡슐화하는 것. 사용자가 보낸 요청을 나중에 이용할 수 있도록 메소드 이름, 매개변수 등 요청에 필요한 정보를 저장 또는 로깅, 취소할 수 있게 만든 패턴 명령 패턴은 메서드 호출을 실체화한 것이다. 명령 패턴은 콜백을 객체지향적으로 표현한 것. 요청을 하는 객체와 그 요청을 수행하는 객체를 분리 한다. 특정 객체에 대한 특정 작업 요청을 캡슐화 한다. 요청 내역을 큐에 저장하거나 로그로 기록할 수 있다. 실행된 작업을 저장해뒀다가 실행취소도 가능하다. 매개변수를 써서 여러 가지 다른 요구 사항을 집어넣을 수도 있다. 외부에서 볼 때 자신이 요청한 명령이 실제로 어떻게 처리되는지 알 수 없게 캡슐화. 그냥 execute 메소드만 호출하면 요구사항이 처리되도록 한다.  Command는 실제로 명령을 수행할 Receiver 객체를 가지고 있다. Command에서 Execute()만 구현해두면 요청하는 쪽에서는 상세를 알 필요가 없다. Execute() 내에서 Receiver 객체를 통해 작업을 수행한다.  Invoker는 Client로부터 전달받은 Command 객체를 통해 명령을 발동한다. Action에 따른 일련의 Command 객체들을 가지고 있을 수도 있다. 필요에 따라 명령 발동 기록을 남긴다.  Receiver는 Command의 Execute()에서 하달받은 명령을 실제로 수행한다.  Client는 어느 시점에 어떤 명령을 수행할지 결정한다. 명령을 수행하려면, Client 객체는 Invoker 객체로 Command 객체를 전달해야 한다. Command, Receiver, Invoker, Client Command 객체는 Receiver를 가지고 있고, Receiver의 메소드를 호출한다.(Execute(), Undo()) Receiver는 자신에게 정의된 메소드를 수행한다. Command 객체는 Invoker 객체에 전달되어 명령을 발동하게 ...