全部版块 我的主页
论坛 新商科论坛 四区(原工商管理论坛) 商学院 运营管理(物流与供应链管理)
96 0
2025-12-12

在家具制造的实际生产过程中,常常会面临这样的问题:当工厂推出新款沙发、衣柜等产品时,需要迅速让经销商准备库存、零售商安排上架,并使潜在客户能够及时获取产品信息。若采用人工逐一电话通知的方式,不仅耗时费力,而且每当新增合作方(如家装公司)时,还需反复调整通知流程。此时,

观察者模式便成为一种理想的解决方案——它构建了一种“一旦工厂(被观察者)状态更新,所有关联方(观察者)自动获知”的高效通信机制。

1. 观察者模式的核心思想

作为一种典型的行为型设计模式,观察者模式的关键在于建立一种一对多的对象依赖关系。当某个“被观察者”(又称主题)的状态发生变更时,所有注册了该主题的“观察者”都会接收到通知,并自动执行相应的更新操作。这种设计的最大优势是实现了被观察者与观察者之间的解耦:两者无需了解对方的具体实现细节,仅通过统一接口进行交互。因此,在增加或移除观察者时,完全不需要修改被观察者的内部逻辑。

以家具生产为例:

  • 被观察者(主题):即家具工厂,负责维护一个观察者列表,并在关键状态变化(如新品下线、产能调整)时触发通知。
  • 观察者:包括经销商、零售商和有购买意向的客户等,他们在接收到通知后,可各自执行备货、上架或咨询等动作。

核心约定:工厂需提供“注册观察者”、“移除观察者”和“通知所有观察者”的标准接口;而每个观察者则必须实现“接收并处理通知”的统一方法。

2. 模式结构解析(结合家具场景)

观察者模式通常由四个基本组件构成,对应到当前应用场景如下:

抽象观察者(Abstract Observer):定义观察者必须遵循的接口规范,其中包含一个用于接收更新的“更新”方法。在本例中,相当于“家具动态关注者”接口,所有希望获取工厂信息的角色都需实现此接口。

具体观察者(Concrete Observer):实现上述抽象接口,具体定义在收到通知后应采取的操作行为。例如经销商根据消息安排进货,零售商准备陈列,客户发起咨询请求等。

抽象被观察者(Abstract Subject):声明被观察者的通用操作接口,包括添加观察者、移除观察者、通知所有观察者的方法,同时包含用于存储观察者列表及自身状态的属性。在此场景中,对应为“家具生产主体”接口。

具体被观察者(Concrete Subject):实现抽象被观察者接口,负责管理自身的业务状态(如当前生产的家具类型、生产进度),并在状态发生变化时主动调用通知机制。这正是“具体家具工厂”的角色体现。

#include <iostream>
#include <vector>
#include <string>
// 提前声明抽象被观察者,解决观察者与被观察者的循环依赖问题
class AbstractFurnitureFactory;

// 1. 抽象观察者:家具关注者(所有关注工厂动态的角色都要实现)
class AbstractObserver {
public:
    // 纯虚函数:接收通知的核心方法,参数为通知内容(家具信息、生产状态等)
    virtual void update(const std::string& furnitureInfo, const std::string& status) = 0;
    // 虚析构:确保子类析构时能正确调用
    virtual ~AbstractObserver() {}
};

// 2. 抽象被观察者:家具生产主体(家具工厂的统一接口)
class AbstractFurnitureFactory {
public:
    // 虚析构
    virtual ~AbstractFurnitureFactory() {}
    // 注册观察者(添加关注者)
    virtual void attach(AbstractObserver* observer) = 0;
    // 移除观察者(取消关注)
    virtual void detach(AbstractObserver* observer) = 0;
    // 通知所有观察者(状态变化时调用)
    virtual void notify() = 0;
    // 设置生产状态(触发通知的条件)
    virtual void setProductionStatus(const std::string& furnitureInfo, const std::string& status) = 0;
};

// 3. 具体被观察者:实木家具工厂(实际生产家具的主体)
class SolidWoodFurnitureFactory : public AbstractFurnitureFactory {
private:
    // 维护观察者列表(关注工厂的所有角色)
    std::vector<AbstractObserver*> observers;
    // 工厂当前生产的家具信息(状态1)
    std::string currentFurniture;
    // 工厂当前生产状态(状态2:如"已下线""生产中""缺货")
    std::string currentStatus;

public:
    // 注册观察者:将观察者加入列表
    void attach(AbstractObserver* observer) override {
        observers.push_back(observer);
        std::cout << "新增关注者成功!" << std::endl;
    }

    // 移除观察者:将观察者从列表中删除
    void detach(AbstractObserver* observer) override {
        for (auto it = observers.begin(); it != observers.end(); ++it) {
            if (*it == observer) {
                observers.erase(it);
                std::cout << "移除关注者成功!" << std::endl;
                return;
            }
        }
        std::cout << "未找到该关注者!" << std::endl;
    }

    // 通知所有观察者:遍历列表,调用每个观察者的update方法
    void notify() override {
        std::cout << "\n=== 实木家具工厂发布通知 ===" << std::endl;
        for (auto observer : observers) {
            // 将当前状态传递给观察者
            observer->update(currentFurniture, currentStatus);
        }
    }

    // 设置生产状态:修改状态后自动触发通知
    void setProductionStatus(const std::string& furnitureInfo, const std::string& status) override {
        currentFurniture = furnitureInfo;
        currentStatus = status;
        // 状态变化,通知所有观察者
        notify();
    }
};

// 4. 具体观察者1:家具经销商(收到通知后备货)
class FurnitureDealer : public AbstractObserver {
private:
    // 经销商名称(区分不同观察者)
    std::string dealerName;

public:
    FurnitureDealer(const std::string& name) : dealerName(name) {}

    // 实现update方法:经销商收到通知后的操作
    void update(const std::string& furnitureInfo, const std::string& status) override {
        if (status == "已下线") {
            std::cout << "经销商【" << dealerName << "】:收到通知!" 
                      << furnitureInfo << "已生产完成,立即安排备货100套!" << std::endl;
        } else if (status == "缺货") {
            std::cout << "经销商【" << dealerName << "】:收到通知!" 
                      << furnitureInfo << "缺货,暂停接单并催促工厂生产!" << std::endl;
        }
    }
};

// 5. 具体观察者2:家具零售商(收到通知后上架)
class FurnitureRetailer : public AbstractObserver {
private:
    // 零售商名称
    std::string retailerName;

public:
    FurnitureRetailer(const std::string& name) : retailerName(name) {}

    // 实现update方法:零售商收到通知后的操作
    void update(const std::string& furnitureInfo, const std::string& status) override {
        if (status == "已下线") {
            std::cout << "零售商【" << retailerName << "】:收到通知!" 
                      << furnitureInfo << "已到店,立即布置展台并上架销售!" << std::endl;
        } else if (status == "缺货") {
            std::cout << "零售商【" << retailerName << "】:收到通知!" 
                      << furnitureInfo << "缺货,立即更新库存标识为'缺货'!" << std::endl;
        }
    }
};

// 6. 具体观察者3:意向客户(收到通知后咨询)
class IntendedCustomer : public AbstractObserver {
private:
    // 客户姓名
    std::string customerName;

public:
    IntendedCustomer(const std::string& name) : customerName(name) {}

    // 实现update方法:客户收到通知后的操作
    void update(const std::string& furnitureInfo, const std::string& status) override {
        if (status == "已下线") {
            std::cout << "客户【" << customerName << "】:收到通知!" 
                      << furnitureInfo << "已生产完成,立即联系门店咨询价格和配送!" << std::endl;
        } else if (status == "生产中") {
            std::cout << "客户【" << customerName << "】:收到通知!" 
                      << furnitureInfo << "正在生产中,等待后续通知!" << std::endl;
        }
    }
};

// 客户端测试:模拟家具生产流程中的通知场景
int main() {
    // 1. 创建被观察者:实木家具工厂
    AbstractFurnitureFactory* factory = new SolidWoodFurnitureFactory();

    // 2. 创建具体观察者:经销商、零售商、客户
    AbstractObserver* dealer = new FurnitureDealer("诚信家具批发部");
    AbstractObserver* retailer = new FurnitureRetailer("宜家家居门店");
    AbstractObserver* customer1 = new IntendedCustomer("张三");
    AbstractObserver* customer2 = new IntendedCustomer("李四");

    // 3. 注册观察者:关注工厂动态
    factory->attach(dealer);
    factory->attach(retailer);
    factory->attach(customer1);

    // 4. 工厂状态变化1:新款实木沙发下线(触发通知)
    factory->setProductionStatus("新款北欧实木沙发(三人位)", "已下线");

    // 5. 移除观察者:客户李四取消关注(先注册再移除,测试移除功能)
    factory->attach(customer2);
    factory->detach(customer2);

    // 6. 工厂状态变化2:实木沙发缺货(触发通知)
    factory->setProductionStatus("新款北欧实木沙发(三人位)", "缺货");

    // 7. 工厂状态变化3:实木衣柜生产中(触发通知)
    factory->setProductionStatus("中式实木衣柜(2米高)", "生产中");

    // 8. 释放资源
    delete customer2;
    delete customer1;
    delete retailer;
    delete dealer;
    delete factory;

    return 0;
}

3. C++ 实现示例(基于家具生产流程)

以下使用 C++ 编写完整的代码实现,涵盖接口定义、具体类实现以及客户端测试逻辑,并配有详细注释说明关键步骤。

notify
AbstractObserver
setProductionStatus
attach
detach

4. 关键特性分析

解耦能力:工厂作为被观察者,无需关心哪些具体的经销商或客户正在监听其状态,只需调用统一的通知接口即可完成广播;当需要引入新的观察者(如家装公司)时,仅需其实现指定接口并向工厂注册,无需改动工厂原有代码。

状态同步机制:一旦工厂通过特定方法更改了生产状态,系统将自动触发通知流程,确保所有已注册的观察者都能及时获得最新信息,从而避免了传统人工逐个通知的低效问题。

灵活的订阅控制:借助“注册”与“注销”功能,观察者可根据实际需求自由加入或退出监听序列,完美契合现实中“客户取消预约”或“经销商终止合作”等常见情况。

5. 适用场景总结

通过家具生产的案例可以看出,当系统中出现以下情形时,应优先考虑采用观察者模式:

  • 某一对象的状态变化需引起多个其他对象同步更新,例如工厂新品发布影响经销商、零售商和客户的决策;
  • 希望降低通知方与接收方之间的耦合度,避免二者直接依赖,比如工厂不必掌握客户的具体信息,仅通过接口传递消息;
  • 要求支持动态增减接收方,如允许家装公司随时接入监控,或客户随时取消关注。

在 C++ 开发实践中,该模式还广泛应用于图形用户界面开发(如按钮点击事件触发多个组件刷新)、日志管理系统(日志级别变更同步至多个输出终端)等场景,是一种高度实用且扩展性强的设计模式。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群