ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Design Pattern] Observer
    개발/C·C++ 2021. 5. 30. 20:19

    옵저버 패턴에 대해 조금 더 깊게 알아야 한다면 다른 글을 참고해주세요. 혹은 GoF나 헤드퍼스트의 디자인 패턴 책을 보면 더욱 자세하고 정확한 설명을 읽을 수 있습니다.

     

    옵저버 패턴은 관찰자(observer)와 관찰 대상(oberservable)이 존재합니다. 관찰자는 관찰 대상의 상태가 변경되면 통지를 받습니다. [헤드퍼스트 디자인 패턴]을 보면, 관찰 대상이 관찰자들에게 notify 함수를 통해 알려주는 부분이 나옵니다. 때문에 관찰자 클래스는 공통된 인터페이스를 상속받아 구현해야 하며, 관찰대상 클래스에서 관찰자를 동적 배열에 추가합니다. 관찰대상이 상태가 업데이트되면 배열에서 객체를 꺼내 필요한 함수를 호출해줍니다. 관찰 대상이 관찰자를 등록할 때 관찰자가 꼭 객체일 필요는 없습니다. 함수를 넣어줘도 됩니다. 이 경우 관찰 대상은 함수 포인터를 통해 관찰자를 관리합니다.

     

    이미지를 맞춰서 점수를 획득하는 보드 게임이 하나 있습니다. 보드 게임을 화면에 띄울 때 필요한 객체는 View 객체, Scene 객체, Board 객체, Board 위에 올라가는 Item 객체, 점수 객체, 점수를 표시해주는 UI 객체 등입니다. 여기에서 관찰 대상은 무엇일까요. 점수입니다. 관찰자는 UI 객체입니다. Board 객체는 관찰자가 아닙니다. Board의 역할은 점수 획득 조건을 판별해 점수를 추가(상태 변경)하는 것입니다. 점수가 바뀔 때 관찰 대상이 등록한 관찰자들에게 바뀐 점수를 통지합니다(notify). 관찰 대상은 다음과 같습니다.

    제너럴하게 사용할 수 있게 클래스 템플릿으로 만들었고 관찰 대상을 한 곳에서 관리하기 위해 Values 구조체에 담았습니다. Values 구조체엔 지금 score만 있지만 필요한 경우에 추가할 수 있습니다. notify() 함수는 벡터로 관리하는 관찰자(함수)에게 갱신된 점수를 넘겨 상태를 업데이트 합니다. 점수를 표시하는 UI 객체에서 생성자를 통해 관찰 대상(Values 객체)에 관찰자(함수)를 넣어줍니다. 아래처럼 람다 표현식을 이용해 익명 함수로 넣어줘도 됩니다. 람다 표현식은 JavaScript에서 함수를 만드는 방법 중 하나와 많이 비슷합니다.

     

    점수 갱신은 Board 객체가 담당하기 때문에 Board의 화면을 갱신하는 함수에서 notify 함수를 호출하면 됩니다. notify 함수를 호출하면 Values 객체는 벡터로 관리하고 있는 관찰자 전부에게 새로운 인수를 넘겨서 값을 갱신하게 합니다.

    위의 반복문에서 const auto& [row, colulmn] : matched 부분을 C++17부터 적용된 구조적 바인딩(structured binding)이라고 하는데요. 이와 비슷한 문법이 JavaScript에서는 ES6(2015)부터 생겼고 구조분해 할당(destructuring assignment)이라고 합니다. 거의 같은 기능인데 표현은 반대인 점이 재미있습니다. 아래가 ES6입니다. 크롬에서 F12 키를 눌러 콘솔창에서 작성했습니다(undefined은 무시해도 됩니다). 지역 변수 a, b, c에 구조분해 할당을 했고 출력했습니다.

    '개발 > C·C++' 카테고리의 다른 글

    WSASend function  (0) 2021.06.06
    IOCP(2)  (0) 2021.06.04
    [Pointer] 정수형을 문자형으로  (0) 2021.05.28
    IOCP(1)  (0) 2021.05.25
    [Rvalue reference] Rvalue Reference(3)  (0) 2021.05.21

    댓글

Designed by Tistory.