본문 바로가기

전체 글

(95)
Command 패턴 커맨드 패턴(C++ 디자인 책 정리)커맨드 디자인 패턴은 (대개) 한 번 그리고 (보통) 즉시 실행하는 작업 꾸러미의 추상화와 분리에 초점을 맞춘다. 커맨드 디자인 패턴의 의도는 다음과 같다.의도: ' 요청을 객체로 캡슐화해 클라이언트를 다른 요청, 큐 또는 로그 요청 등으로 매개변수화하고 실행 취소할 수 있는 연산을 지원하게 한다.' OO 기반 형식에서 커맨드 패턴은 Command 기초 클래스 형식의 추상화를 도입한다. 이를 통해 누구나 새 ConcreateCommand를 구현할 수 있다. 그 ConcreteCommand는 무엇이든 할 수 있으며 심지어 Receiver에 행동을 수행할 수도 있다.명령 효과는 특정 Invoker가 추상 기초 클래스를 통해 유발한다. 커맨드 디자인 패턴의 구체적인 예로 다..
Strategy 패턴 전략 패턴(C++ 소프트웨어 디자인 책 정리)전략 디자인 패턴의 의도는 다음과 같다. '알고리즘 군을 정의하고 각각을 캡슐화해 상호 교환이 가능하게 한다. 전략을 사용하면 알고리즘 사용하는 클라이언트와 독립적으로 알고리즘을 변경할 수 있다' 지난 visitor 패턴에서 사용한 주제로 전략 디자인 패턴을 UML로 표현하면 다음과 같다. 파생 클래스에서 가상의 draw() 함수를 구현하는 대신 여러분은 도형 그리기를 위해 다른 클래스를 도입한다.전략 디자인 패턴의 고전적인 객체 지향 형식의 경우 DrawStrategy기본 클래스를 도입해  이를 해낸다. 위 UML처럼 그리기 관심사의 격리로 이제 도형 클래스를 수정하지 않고 그리기 구현을 변경할 수 있다.//----- ------class Circle;cl..
Visitor 패턴 (std::variant) (C++ 소프트웨어 디자인 책 정리)  앞서 구현한 Visitor 패턴을 std::variant, std::visit을 사용해서 구현해보자. std::variantstd::variant 는 변수를 여러 타입을 선택하여 만든 후 선택한 타입 중 하나만 담을 수 있다.아래 main() 예시를 보자.int main(){ //0으로 초기화한 'int'를 담고 있는 기본 variant를 생성한다. std::variant v{}; v = 42; //'int' 형 에 대입 v = "Hyojin" // 문자열 string 에 대입 v = 3.14 // 'double' 대입 int tmp = std::get(v); // 값에 직접 접근한다 (참조형으로 return) int pTmp = std::get..
Visitor 패턴 (C++ 소프트웨어 디자인 책 정리) 비지터 디자인 패턴은 GoF 서술한 고전적인 디자인 패턴 중 하나다. 타입보다는 연산을 자주 추가할 수 있게 하는데 중점을 둔다.비지터 패턴의 의도는 객체 구조의 요소에 대해 수행할 연산을 나타낸다. 비지터를 사용하면 연산 대상 요소의 클래스를 변경하지 않고 새 연산을 정의할 수 있다. 아래 shape의 상송 계통을 보자 위 UML 에서 Shape클래스는 특정 도형에 대한 기초 클래스다. 지금 예에서는 Circle, Square, Trapezoid  클래스가 있다. 위 구조를 가지고 유지보수를 하던 중 새로운 연산 'rotate 함수' 를 구현해야 한다고 하자. Shape 클래스에 'rotate'연산을 추가하고 직접 정의한 파생 타입은 약간의 추가 노력으로 훌훌 털어..
DIP 원칙 의존성 역전 원칙(Dependency Inversion Principle, DIP) (C++ 소프트웨어 디자인 책 정리)가장 유연한 시스템은 소스 코드 의존성이 구체화(concretion)가 아닌 추상화만 참조하는 시스템이다. 이 원칙은 의존성을 위해 구체 타입이나 구현 상세 대신 추상화에 의존할 것을 조언한다.상속 계통에 대해서는 아무 말도 하지 않고 일반적인 추상화만 언급한다. 지금부터 자동 입출금기(ATM)의 논리를 구현한다고 생각해보자. ATM은 인출, 입금, 송금 등 여러가지 연산을 제공한다. 이 모든 연산은 실제 돈을 다루므로 완전히 완료하거나 오류가 있으면  중단하고 모든 변경을 되돌려야 한다. 이런 행위를 일반적으로 transaction 이라고 한다.결과적으로 Transaction이라는 추..
LSP 원칙 리스코프 치환 원칙 (C++ 소프트웨어 디자인 책 정리)하위 타입(subtype) 요구 사항: ψ(x) 를 T 타입 객체 x에 대해 증명할 수 있는 특성이라 하자. 이 때 S가 T의 하위 타입이라면 ψ(y)는 S 타입 객체 y에 대해 참이어야한다. LSP는 세 번쨰 SOLID원칙이며 행위적 서브타이핑, 즉 추상화로 기대하는 행위와 관련이 있다.이 원칙은 흔히 IS-A 관계라고 하는 것을 공식화 한다. 이 관계, 즉 추상화의 기대를 하위타입에서 반드시 따라야 한다.Struct X{ virtual ~X() = default; // 사전 조건: 함수는 0보다 큰 모든 'i'를 받아들인다 virtual void f( int i) const { assert(i > 0); // ... }};..
OCP 원칙 개방-폐쇄 원칙(Open-Close Principle OCP)(C++ 소프트웨어 디자인 책 정리)(클래스, 모듈, 함수 등) 소프트웨어 산출물은 확장에는 열려 있지만 수정에는 닫혀 있어야 한다. OCP는 소프트웨어를 확장할 수 있어야 한다고 말한다(확장에 열려 있음). 하지만 확장이 쉬워야 하고, 최선의 경우 새 코드를 추가하는 것만으로 확장 가능해야 한다. 즉, 기존 코드를 수정할 필요가 없어야 한다(수정에 닫혀 있음). 위 원칙을 설명하기 앞서 다른 원칙에서 설명을 했던 Document 클래스를 살펴보자.class Document{ public: // ... virtual ~Document() = default; virtual void exportToJSON( /*...*/ ) const ..
ISP 원칙 인터페이스 분리 원칙 (Interface Segregation Principle ISP)(C++ 소프트웨어 디자인 책 정리)사용하지 않는 메서드에 클라이언트가 의존하도록 강요해서는 안 된다. 앞서 SRP 법칙의 document  예제를 다시 보자.이번에는  document 클래스의 개별 함수가 아닌 전체 인터페이스에 집중한다.class Document{ public: // ... virtual ~Document() = default; virtual void exportToJSON( /*...*/ ) const = 0; virtual void serialize( ByteStream bs, /*...*/) const = 0; //...}; Document에는  JSON 내보내기와 직렬화를 모두..