본문 바로가기

728x90

전체 글

[디자인패턴][행위패턴] 상태 State - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. State Pattern 상태에 의해 행동이 결정된다. 상태는 바뀔 수 있고, 상태를 전환시켜 주는 것을 트리거라 한다. 상태 디자인 패턴은 "상태가 동작을 제어하고, 상태는 바뀔 수 있다"는 단순한 아이디어다. 상태 변경 주체가 누구인지 규정하지 않는다. 상태 디자인 패턴은 보통 두 가지 방법이 있다. 실제로는 두 번째 방법이 더 흔히 사용된다. 첫 번째 방법은 일반적인 사고방식과 색다른 면이 있다. 동작을 가지는 실제 클래스로 상태를 정의한다. 상태가 이전될 때 클래스의 변화에 따라 변경된다. 상태와 상태 전이를 단순히 enum 타입처럼 식별자의 나열로 정의한다. 실제 상태 변화는 상태 머신이라는 특별한 컴포넌트를 두어 수행.. 더보기
[디자인패턴][행위패턴] 관찰자 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 클래스의 정의에.. 더보기
[디자인패턴][행위패턴] 매개자 Meditator - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. Meditator Pattern 우리가 작성하는 코드의 상당 부분은 서로 다른 컴포넌트(클래스) 간 포인터나 직접적 참조를 통해 커뮤니케이션한다. 어떤 경우 컴포넌트 간 명시적으로 상대방 객체의 존재를 알아야 하는 상황이 불편할 수 있다. 또는 상대방 객체를 알더라도 객체 생성/소멸 시점에 대한 관리 때문에 포인터나 참조로 접근되는 것이 싫을 수 있다. 매개자는 컴포넌트 간 커뮤니케이션을 돕기 위한 메커니즘이다. 매개자 자체는 커뮤니케이션에 동반되는 모든 컴포넌트로부터 접근 가능해야 한다. 즉, 전역 정적 변수이거나 모든 컴포넌트에 참조가 노출되어야 한다. 채팅 룸 채팅 룸은 매개자 디자인 패턴이 적용될 수 있는 가장 전형적인 .. 더보기
[디자인패턴][행위패턴] 반복자 Iterator - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. Iterator Pattern 복잡한 데이터 구조를 다뤄야 할 때 데이터 순회(traversal) 문제에 부딪힌다. 여러 방법이 있지만 vector 형태의 데이터에서는 반복자(iterator)라고 불리는 방법이 흔히 사용된다. 반복자는 단순히 어떤 컬렉션의 항목 하나에 접근하는 방법과 그 항목의 다음 항목으로 이동하는 방법을 알고 있는 것이다. 따라서 ++ 연산자와 != 연산자만 구현하면 된다. C++ 표준 라이브러리에서도 반복자를 광범위하게 사용하고 있다. 먼저 C++ 표준 라이브러리가 반복자를 어떻게 사용하고 있는지 알아볼 것이다. 그다음 직접 반복자를 만들고 반복자가 가진 제약들을 살펴본다. 표준 라이브러리 반복자 vect.. 더보기
[디자인패턴][행위패턴] 인터프리터 Interpreter - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. Interpreter Pattern Interpreter 디자인 패턴의 목적은 입력 데이터를 해석하는 것이다. 꼭 텍스트에 한정되지는 않는다. 인터프리터의 작업을 수행하는 몇 가지 단순한 예를 보여줄 것이다. 일반적인 예는 다음과 같다. 42나 1.234e12와 같은 숫자 리터럴은 바이너리로 저장하면 효율적이다. C++에서는 Boost.LexicalCast와 같은 고급 라이브러리를 사용할 수 있다. C의 API인 atof()를 이용할 수도 있다. 텍스트에서 어떤 패턴을 찾을 때 정규 표현식을 사용하면 편하다. 정규 표현식은 특정 목적을 위한 완전 별개의 언어다. 정규 표현식도 적절히 해석되어야만 한다. CSV, XML, JSON.. 더보기
[디자인패턴][행위패턴] 커맨드 Command - C++ [모던 C++ 디자인 패턴] 책을 바탕으로 공부하는 내용을 정리한 내용이다. Command Pattern 커맨드 패턴은 어떤 객체를 활용할 때 직접 그 객체의 API를 호출해 조작하는 대신, 작업을 어떻게 하라고 명령을 보내는 방식을 제안한다. 여기서 명령은 무엇을 어떻게 하라는 지시가 담긴 클래스 그 이상도 이하도 아니다. 시나리오 은행의 마이너스 통장을 생각해 보자. 마이너스 통장은 잔고와 인출 한도가 있다. 입금과 출금 동작을 수행해야 한다. 이때 모든 입출금 내역을 기록해야 한다고 하자. 또한, 입출금 클래스는 이미 기존에 만들어져 검증되었고 동작 중이어서 수정할 수 없는 상황이다. struct BankAccount { int balance = 0; int overdraft_limit = -500.. 더보기

728x90