반응형
이전 글에서는 퍼사드(Facade) 패턴을 모던 C++ 관점에서 재해석하며, 상속 없이 람다와 함수 합성으로 복잡한 서브시스템을 단순한 인터페이스로 감싸고, std::expected, std::format, coroutine, Ranges 등을 활용해 비동기 처리나 조건부 처리, 로깅, 에러 처리 등 다양한 요구사항에 쉽게 대응할 수 있음을 확인했습니다. 이번에는 구조적 패턴 중 플라이웨이트(Flyweight) 패턴을 다룹니다.플라이웨이트 패턴은 많은 수의 유사한 객체를 효율적으로 관리하기 위해 객체들이 공유할 수 있는 상태를 중앙에서 관리하는 패턴입니다. 예를 들어, 텍스트 처리기에서 각 문자를 개별 객체로 표현하면 메모리 낭비가 심하므로, 공유 가능한 폰트 정보나 형태 정보를 플라이웨이트 객체로 한 ..
이전 글에서는 데코레이터(Decorator) 패턴을 모던 C++ 관점에서 재해석하며, 상속 없이도 람다 합성을 통해 객체에 동적으로 기능을 추가하는 방법을 살펴봤습니다. 이번에는 구조적 패턴 중 퍼사드(Facade) 패턴을 다룹니다.퍼사드 패턴은 복잡한 서브시스템을 단일하고 단순한 인터페이스로 감싸, 클라이언트가 시스템을 쉽게 사용할 수 있게 하는 패턴입니다. 전통적으로는 Facade 클래스를 만들어 서브시스템 객체들을 정적 호출 계층으로 감싸았으나, 이는 서브시스템 변경 시 Facade 수정 필요, 에러 처리나 비동기 처리 시 복잡성 증가 등의 문제를 야기합니다.C++20 이상에서는 Concepts, 람다, std::function, std::expected, std::format, coroutine,..
이전 글에서는 컴포지트(Composite) 패턴을 모던 C++ 관점에서 재해석하며, std::variant와 std::visit를 통해 상속 없이 부분-전체 구조를 값 기반으로 표현하고, Ranges, coroutine, std::expected, std::format 등을 활용해 조건부 처리, 비동기 연산, 로깅 등 다양한 요구사항에도 쉽게 대응할 수 있음을 확인했습니다. 이번에는 구조적 패턴 중 데코레이터(Decorator) 패턴을 다룹니다.데코레이터 패턴은 객체에 동적으로 새로운 기능을 추가하기 위한 패턴이며, 전통적 구현에서는 컴포넌트를 상속한 데코레이터 클래스 계층을 통해 기능을 장식(Decorate)해야 했습니다. 그러나 이는 클래스 증가와 유지보수 어려움을 초래합니다. C++20 이상에서는 ..
이전 글에서는 어댑터(Adapter) 패턴을 모던 C++ 관점에서 재해석하며, 기존 인터페이스를 원하는 다른 인터페이스로 변환하기 위해 상속 없이도 람다, Concepts, std::expected, std::format, coroutine, Ranges 등을 활용할 수 있음을 확인했습니다. 이번에는 구조적 패턴 중 브리지(Bridge) 패턴을 다룹니다.브리지 패턴은 추상(Abstraction)과 구현(Implementation)을 분리하여 둘을 독립적으로 확장 가능하게 만드는 패턴입니다. 전통적으로는 추상 클래스 계층과 구현 클래스 계층을 상속 기반으로 구분하고, 추상 클래스가 구현 객체를 참조하는 구조를 사용했습니다. 이 방식은 새로운 추상이나 구현 타입 추가 시 클래스 증가와 복잡성 상승을 초래합니..
이전 글에서는 비지터(Visitor) 패턴을 모던 C++ 관점에서 재해석하며, std::variant와 std::visit를 통해 이중 디스패치 없이도 다양한 요소 타입별 로직을 처리하는 법을 살펴보았습니다. 이제는 구조적(Structural) 패턴 중 하나인 어댑터(Adapter) 패턴을 다룹니다.어댑터 패턴은 기존 클래스나 함수 인터페이스를 클라이언트가 원하는 다른 인터페이스로 변환하는 패턴입니다. 전통적으로는 어댑터 클래스를 상속 기반으로 정의하고, 기존 인터페이스를 변환하는 메서드를 구현했지만, 이 방식은 클래스 증가, 상속 기반 구조로 인한 유지보수 어려움을 야기합니다.C++20 이상에서는 Concepts로 원하는 인터페이스 요구사항을 명시하고, 람다나 함수 합성으로 변환 로직을 구현하면 상속 ..
이전 글에서는 메멘토(Memento) 패턴을 모던 C++ 관점에서 재해석하며, 상속 없이 값 기반 상태 스냅샷과 std::expected, coroutine, Ranges 등을 활용해 Undo/Redo, 비동기 복원, 로깅 등의 요구사항에 대응할 수 있음을 확인했습니다. 이번에는 행동(Behavioral) 패턴 중 템플릿 메서드(Template Method) 패턴을 다룹니다.템플릿 메서드 패턴은 상위 클래스에서 알고리즘의 골격(템플릿)을 정의하고, 하위 클래스에서 일부 단계를 오버라이드하여 구체화하는 패턴입니다. 그러나 전통적 접근은 상속 기반 구조로, 알고리즘 변형 시 하위 클래스 증가, 유지보수 어려움 등이 발생합니다. C++20 이상에서는 Concepts, 람다, std::expected, std:..
이전 글에서는 이터레이터(Iterator) 패턴을 모던 C++ 관점에서 재해석하며, C++20 Ranges와 Concepts를 통해 상속 없이도 선언적이고 타입 안전한 순회 방식을 구현할 수 있음을 확인했습니다. 이번에는 행동(Behavioral) 패턴 중 미디에이터(Mediator) 패턴을 다룹니다.미디에이터 패턴은 객체들이 서로 직접 통신하는 대신, 미디에이터(중재자)를 통해 상호작용하도록 하여 객체 간 결합을 느슨하게 만드는 패턴입니다. 전통적으로는 미디에이터 인터페이스와 구체 미디에이터를 상속 기반으로 정의하고, 각 객체가 미디에이터를 참조해 메시지나 이벤트를 중개하는 구조를 사용했습니다. 그러나 모던 C++20 이상에서는 Concepts, 람다, std::function, std::expecte..
커맨드(Command) 패턴은 실행할 작업(명령)을 객체로 캡슐화하여, 명령을 매개변수로 전달하거나 큐잉, Undo/Redo, 비동기 실행 등의 기능을 가능하게 하는 중요한 패턴입니다. 하지만 전통적 구현(특히 C++98/03, 심지어 C++11/14/17 시절)에서는 다음과 같은 단점이 있었습니다.전통적 방식:추상 커맨드 인터페이스(abstract Command) 정의이를 상속하는 구체 커맨드 클래스 다수 정의 → 클래스 수 증가, 유지보수성 저하Undo/Redo, 비동기 처리, 로깅 추가 시 복잡성 폭발명령 교체, 에러 처리 등 구현이 번거로움하지만, C++20 이상 모던 C++에서는 람다, std::function, Concepts, std::expected, std::format, coroutin..
이전 글에서는 상태(State) 패턴을 모던 C++ 관점에서 재해석하며, 상속 기반 상태 클래스와 vtable에 의존하지 않고 std::variant, std::visit, Concepts, std::expected, std::format, Coroutines 등을 활용해 더 선언적이고 유지보수성 높은 상태 전이 로직을 구현할 수 있음을 확인했습니다. 이번에는 행동(Behavioral) 패턴 중 책임 연쇄(Chain of Responsibility) 패턴을 다룹니다.책임 연쇄 패턴은 요청(request)이 처리될 수 있는 핸들러(handler)들을 체인 형태로 연결하고, 각 핸들러가 요청을 처리하거나 다음 핸들러로 넘기는 구조를 제안합니다. 전통적으로는 상속 기반 핸들러 클래스 계층을 정의하고, setN..
지난 글에서는 전략(Strategy) 패턴을 모던 C++ 관점에서 재해석하며, 상속과 가상 함수를 통한 고전적 접근 대신 Concepts, 람다, std::function, std::expected, std::format 등 현대적 언어 기능을 활용해 상속 없이도 유연한 알고리즘 선택을 구현할 수 있음을 확인했습니다. 이번 글에서는 행동(Behavioral) 패턴 중 또 하나의 대표 주자인 옵저버(Observer) 패턴을 다룹니다.옵저버 패턴은 객체 간의 1:N 의존성을 정의해, 한 객체의 상태 변화 시 이를 의존하는 다른 객체(옵저버)에게 자동으로 통지하는 패턴입니다. 전통적으로는 "Subject가 Observer 리스트를 관리"하고 "상속 기반의 Update() 가상 함수 호출"을 통해 알림을 전달했..