본문 바로가기
SW

GoF의 디자인 패턴(Design Patterns: Elements of Reusable Object-Oriented Software) - 2장 사례 연구:문서 편집기 설계(2.7)

by 라꾸스떼(YR) 2020. 4. 13.
반응형

[2.7 사용자 조작]

WYSIWYG. 즉, 텍스트를 입력,삭제하며 삽입 지점으로 커서를 이동하고 텍스트의 범위를 선택하는 기능은 문서 화면을 마우스로 직접 클릭하고 키보드로 타이핑함으로써 가능하다.

사용자 조작을 어느 특정 사용자 인터페이스에만 국한시키고 싶지는 않다. 왜냐하면 여러 개의 사용자 인터페이스가 동일한 연산을 수행할 수도 있기 때문이다. 예를 들어, 페이지를 바꾸기 위해서 메뉴를 이용할 수도 있고, 페이지 이동 버튼을 이용할 수도 있다. 게다가, 한 가지의 조작 기능은 여러 다른 클래스들에서 구현된다. 구현자 쪽에서는 이런 기능을 위해 구현과 사용자 인터페이스 클래스 사이에 종속성을 만든느 일은 하지 않으려고 한다. 결합도가 강한 구현을 만들게 되면 이해하기도 어렵고 확장이나 유지보수가 어려워지기 때문이다.

 

[요청의 캡슐화]

호출할 함수로 MenuItem 클래스를 매개변수화할 수도 있겠지만, 이것도 다음 세가지 이유 때문에 완벽한 해법이 되지는 못하다.

1.실행,취소 문제를 처리할 수 없다.

2.함수에 상태를 결합시키기 어렵다.

3.함수를 확장하기 어렵고, 함수의 일부를 재사용하기도 쉽지 않다.

이런 이유로, 함수를 매개변수로 받는 것이 아니라 객체를 MenuItem 매개변수로 정의하려 한다. 이렇게 하면, 상속을 통해서 요청 구현을 확장하거나 재사용할 수 있다. 게다가, 실행,취소 서비스를 구현할 수 있고 상태를 저장할 수 있는 공간을 객체 안에 정의할 수도 있다.

 

[Command 클래스와 서브클래스]

먼저, 요청을 발생시키는 인터페이스를 제공하기 위해 Command 추상 클래스를 정의한다. 이 인터페이스는 요청 발생용 인터페이스의 기본으로, “Execute” 추상 연산 하나만 있다. 버튼과 다른 위젯들도 이와 동일한 방식으로 명령들을 처리한다는 점도 주목할 부분이다.

 

[취소 가능성]

실행,취소는 대화식 응용프로그램에서 중요한 기능이다. 명령을 실행하고 취소하기 위해서는 Command 인터페이스에 Unexecute() 연산을 추가해야 한다. Unexecute() 연산은 바로 전에 수행한 연산의 처리 결과를 되돌리는 것이다. 이를 위해서는 Execute() 연산이 저장한 취소 정보(undo information)를 이용한다. 가끔 이런 취소 가능성(undoability)을 런타임에 결정해야 할 때도 있다. 명령을 수행한 후 나타난 결과에 어떠한 영향도 미치지 못했다면 해당 취소 명령도 수행할 필요가 없다.

그러므로 명령이 취소 가능한 것인지 아닌지를 판단하기 위해서는 Command 인터페이스에 Reversible() 연산을 추가해야 한다. Reversible()연산은 boolean 값을 반환하는 연산으로, 각 서브클래스에서 이 연산이 취소 가능한지 아닌지를 판단하여 참 또는 거짓을 반환하도록 재정의할 수 있다.

 

[명령 이력]

실행과 취소를 임의 수준으로 지원하도록 만드는 작업의 마지막 단계는 명령 이력(command history)을 정의하는 것이다. 즉, 실행한(취소된 명령이 있을 때에는 실행이 취소된) 명령의 리스트를 관리하는 것이다.

 

[명령 패턴]

Lexi의 사용자 명령어는 명령 패턴을 응용한 것으로, 명령 패턴은 요청을 어떻게 캡슐화하는지 설명하는 패턴이다. 명령 패턴은 요청을 발생시키는 데 필요한 균일한 인터페이스를 규정해 주기 때문에, 사용자 쪽에서는 서로 다른 요청을 동일하게 처리할 수 있다. 또한, 이 패턴에는 취소와 재실행을 처리하는 인터페이스를 추가할 수도 있다.

반응형

댓글