본문 바로가기

728x90

행위 패턴

[디자인패턴][행위패턴] 방문자 Visitor - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. Visitor Pattern 계층을 이루는 클래스들을 사용해야 할 때, 소스 코드를 수정할 수 없다면 각 계층마다 멤버 함수를 추가하는 것이 불가능하다. 이 문제를 해결하기 위한 방문자 패턴은, 사용하기 위해서는 선제적으로 어떤 준비가 되어야 있어야만 한다. 침습적 방문자 가장 직접적인 접근 방법부터 시도해 보자. 이 방법은 OCP에 위배된다. 수학 수식을 파싱해야 할 때, Expression 인터페이스를 직접적으로 수정하는 방법이다. 상속 관계에 따라 모든 하위 클래스도 수정된다. struct Expression { virtual void print(ostringstream &oss) = 0; }; OCP 원칙을 위배하는 것과.. 더보기
[디자인패턴][행위패턴] 템플릿 메서드 - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. Template Method 전략 패턴과 매우 유사하다. 차이점은 전략 패턴이 컴포지션을 이용하는 데 반해 템플릿 메서드 패턴은 상속을 이용한다는 것이다. 하지만 핵심 원리는 어떤 알고리즘의 골격을 한 곳에 정의해 두고 상세 구현을 다른 곳에 둔다는 점에서 동일하다. 이 부분은 시스템 확정 측면에서 OCP 원칙을 준수하는 것이다. 게임 시뮬레이션 보드 게임을 예로 들어 아래와 같이 알고리즘을 정의해보자. 게임 실행 시에는 run() 메서드는 다른 메서드를 호출할 뿐이다. 그 메서드들은 퓨어 버추얼이면서 protected이기 땜누에 다른 쪽에서 호출할 수는 없다. class Game { private: void run() { st.. 더보기
[디자인패턴][행위패턴] 전략 Strategy - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. Strategy Pattern 배열에 문자열 여러 개를 목록 정리해서 출력하려고 한다고 해보자. HTML이나 LaTeX의 경우 목록을 표현하기 위해서는 그 렌더링 언어만의 열림/닫힘 태그가 필요하다. 목록을 출력하는 일은 여러 경우마다 비슷한 부분이 있기도 하고 다른 부분도 있기도 하다. 이때 각 경우들 하나하나를 별개의 "전략"으로 취급할 수 있다. 목록을 출력하는 작업은 다음과 같은 전략으로 공식화할 수 있다. 이때 서로 다른 포맷마다 서로 다른 전략을 공식화하고 각 전략은 일반화되어 불변하는 상위 수준 텍스트 출력 알고리즘에 입력돼 세부 동작에 가변성을 부여할 수 있다. 목록의 열림 태그와 항목을 출력한다. 목록의 각 항목.. 더보기
[디자인패턴][행위패턴] 관찰자 Observer - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. Observer Pattern 관찰자 패턴은 널리 사용되는 패턴이다. 다른 언어들에서는 언어 자체적으로 또는 표준 라이브러리에서 관찰자 패턴을 지원한다. C++을 제공되지 않는다. 제대로 된 관찰자 패턴은 기술적으로 매우 정교한 구현을 요구한다. 속성 관찰자 생일잔치를 챙겨주도록 해보자. 사람의 나이가 바뀌는 것을 어떻게 알 수 있을까? 변경을 알아채는 방법에는 폴링(polling)을 사용할 수도 있다. 이러한 방법은 효과는 있지만 비효율적이다. 사람의 나이가 변경될 때 정보를 받는 것이 가장 효과적이다. 그러기 위해서는 set 멤버 함수가 필요하다. 이제 set 멤버 함수가 호출될 때 알림을 보낼 수 있으면 된다. Observ.. 더보기
[디자인패턴][행위패턴] Null 객체 - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. Null 객체 인터페이스를 마음대로 선택할 수 있는 경우는 사실 그렇게 많지 않다. 어떤 모듈의 특정 기능을 원하지 않지만 인터페이스에 이미 내장되어 있을 수 있다. 이때 Null 객체를 이용한다. 시나리오 우선 아래와 같은 인터페이스를 갖는 Logger 라이브러리를 사용한다고 가정하자. struct Logger { virtual ~Logger() = default; virtual void info(const string &s) = 0; virtual void warn(const string &s) = 0; }; 이 라이브러리를 이용해 다음과 같이 은행 계좌 동작들에 로깅 기능을 구현해 보자. void BankAccount::d.. 더보기
[디자인패턴][행위패턴] 메멘토 Memento - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. Memento Pattern 커맨드 디자인 패턴에서 시스템의 모든 변경 이력을 기록한다면, 이론적으로 과거의 어떤 지점으로든 상태를 되돌릴 수 있다는 것을 이미 살펴봤다. 여기서 임의의 과거가 아니라 필요할 때 특정 시점으로 되돌릴 수만 있으면 충분한 경우가 있다. 그것이 메멘토 패턴이 필요한 경우다. 메멘토는 특정 시점의 상태를 전용 객체로 저장해 리턴한다. 이 객체는 읽기 전용 속성을 가지며 그 자체적으로는 어떤 동작도 하지 않는다. 이러한 "토큰"의 객체는 필요할 때 시스템에 주입되어 저장된 상태로 되돌린다. 은행 계좌 앞서 매개자 패턴에서 살펴보았던 은행 계좌 예를 이어서 볼 것이다. BankAccount 클래스의 정의에.. 더보기
[디자인패턴][행위패턴] 반복자 Iterator - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. Iterator Pattern 복잡한 데이터 구조를 다뤄야 할 때 데이터 순회(traversal) 문제에 부딪힌다. 여러 방법이 있지만 vector 형태의 데이터에서는 반복자(iterator)라고 불리는 방법이 흔히 사용된다. 반복자는 단순히 어떤 컬렉션의 항목 하나에 접근하는 방법과 그 항목의 다음 항목으로 이동하는 방법을 알고 있는 것이다. 따라서 ++ 연산자와 != 연산자만 구현하면 된다. C++ 표준 라이브러리에서도 반복자를 광범위하게 사용하고 있다. 먼저 C++ 표준 라이브러리가 반복자를 어떻게 사용하고 있는지 알아볼 것이다. 그다음 직접 반복자를 만들고 반복자가 가진 제약들을 살펴본다. 표준 라이브러리 반복자 vect.. 더보기
[디자인패턴][행위패턴] 커맨드 Command - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. Command Pattern 커맨드 패턴은 어떤 객체를 활용할 때 직접 그 객체의 API를 호출해 조작하는 대신, 작업을 어떻게 하라고 명령을 보내는 방식을 제안한다. 여기서 명령은 무엇을 어떻게 하라는 지시가 담긴 클래스 그 이상도 이하도 아니다. 시나리오 은행의 마이너스 통장을 생각해 보자. 마이너스 통장은 잔고와 인출 한도가 있다. 입금과 출금 동작을 수행해야 한다. 이때 모든 입출금 내역을 기록해야 한다고 하자. 또한, 입출금 클래스는 이미 기존에 만들어져 검증되었고 동작 중이어서 수정할 수 없는 상황이다. struct BankAccount { int balance = 0; int overdraft_limit = -500.. 더보기

728x90