[Day19] Observer Pattern with DeliveryService

베리투스·2025년 8월 29일

TIL: Today I Learned

목록 보기
27/93

이번 학습에서는 Observer 패턴을 이해하고 직접 코드로 구현했다. 😎 DeliveryService(Subject)가 상태를 관리하고, 여러 Customer(Observer)들에게 알림을 전달하는 구조를 실습했다. ✍️


📌 목표

  • Observer 패턴의 기본 구조 이해
  • C++에서 클래스 상속과 순수 가상 함수 활용
  • 고객 유형별(일반/VIP/기업) 다형성 구현

💻 코드

main.cpp

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

// 고객에게 알림을 전달하는 인터페이스 역할
class Customer {
public:
    // 순수 가상 함수: 배송 상태를 업데이트 받을 때 호출됨
    virtual void update(const string& status) = 0;
};

// 여러 고객을 관리하고, 배송 상태를 알리는 서비스 클래스
class DeliveryService {
private:
    vector<Customer*> customers;   // 고객 객체들을 저장
    string currentStatus;          // 현재 배송 상태

public:
    // 고객 등록
    void addCustomer(Customer* customer) {
        customers.push_back(customer);
    }
    // 고객 제거 (remove-erase idiom 사용)
    void removeCustomer(Customer* customer) {
        customers.erase(remove(customers.begin(), customers.end(), customer), customers.end());
    }
    // 배송 상태 갱신 및 고객 알림
    void updateStatus(const string& status) {
        currentStatus = status;
        notifyCustomers();
    }
    // 등록된 모든 고객에게 상태 변경을 통지
    void notifyCustomers() {
        for (Customer* customer : customers) {
            customer->update(currentStatus);
        }
    }
};

// Customer 인터페이스를 상속받는 일반 고객 클래스
class RegularCustomer : public Customer {
private:
    string name;
public:
    // 생성자: 고객 이름 초기화
    RegularCustomer(const string& name) : name(name) {}
    // 일반 고객용 알림 메시지 출력
    void update(const string& status) {
        cout << "Regular customer " << name << " received update: " << status << endl;
    }
};

// Customer 인터페이스를 상속받는 VIP 고객 클래스
class VIPCustomer : public Customer {
private:
    string name;
public:
    // 생성자: 고객 이름 초기화
    VIPCustomer(const string& name) : name(name) {}
    // VIP 고객용 알림 메시지 출력
    void update(const string& status) {
        cout << "VIP customer " << name << " received VIP update: " << status << endl;
    }
};

// Customer 인터페이스를 상속받는 기업 고객 클래스
class BusinessCustomer : public Customer {
private:
    string name;
public:
    // 생성자: 고객 이름 초기화
    BusinessCustomer(const string& name) : name(name) {}
    // 기업 고객용 알림 메시지 출력
    void update(const string& status) {
        cout << "Business customer " << name << " received business update: " << status << endl;
    }
};

// 실행 시작점
int main() {
    // 배송 서비스 객체 생성
    DeliveryService service;

    // 고객 객체 동적 생성
    RegularCustomer* customer1 = new RegularCustomer("Alice");
    VIPCustomer* customer2 = new VIPCustomer("Bob");
    BusinessCustomer* customer3 = new BusinessCustomer("CompanyX");

    // 고객 등록
    service.addCustomer(customer1);
    service.addCustomer(customer2);
    service.addCustomer(customer3);

    // 배송 상태 갱신 및 알림
    cout << "Updating status: 배송 준비 중" << endl;
    service.updateStatus("배송 준비 중");

    cout << "\nUpdating status: 배송 완료" << endl;
    service.updateStatus("배송 완료");

    // 메모리 해제 (메모리 누수 방지)
    delete customer1;
    delete customer2;
    delete customer3;

    return 0;
}

⚠️ 실수

  • notifyCustomers를 처음엔 "고객 값 수정"이라고 잘못 이해했다. 실제로는 서비스의 현재 상태를 전달하는 역할이다. 고객 객체의 내부 상태는 직접 바뀌지 않는다.
  • 클래스 기능을 애매하게 이해했다. “배달 기능” 정도로만 생각해서 오해 소지가 있었고, 정확히는 “상태 변경을 여러 고객에게 알리는 서비스(Observer의 Subject)”라고 이해하는 것이 맞다.
  • 코드를 작성할 때 생성자의 역할을 헷갈렸다. 단순히 이름을 전달받아 멤버 변수를 초기화하는 것인데, 처음에는 복잡한 동작이 있을 거라고 착각했다 🤔 결국은 멤버 초기화 리스트로 값만 세팅하는 단순한 부분이었다.

✅ 핵심 요약

개념설명비고
Observer 패턴Subject(DeliveryService)가 상태를 관리하고, Observer(Customer)에게 알림을 전달디자인 패턴 학습
순수 가상 함수자식 클래스가 반드시 구현해야 하는 함수다형성 기반
remove-erase idiomvector에서 특정 원소 제거할 때 쓰는 패턴C++ STL 필수 테크닉
메모리 관리new로 생성한 객체는 delete로 해제 필요실무에선 스마트포인터 권장
profile
Shin Ji Yong // Unreal Engine 5 공부중입니다~

0개의 댓글