在家具制造的实际生产过程中,常常会面临这样的问题:当工厂推出新款沙发、衣柜等产品时,需要迅速让经销商准备库存、零售商安排上架,并使潜在客户能够及时获取产品信息。若采用人工逐一电话通知的方式,不仅耗时费力,而且每当新增合作方(如家装公司)时,还需反复调整通知流程。此时,
观察者模式便成为一种理想的解决方案——它构建了一种“一旦工厂(被观察者)状态更新,所有关联方(观察者)自动获知”的高效通信机制。
作为一种典型的行为型设计模式,观察者模式的关键在于建立一种一对多的对象依赖关系。当某个“被观察者”(又称主题)的状态发生变更时,所有注册了该主题的“观察者”都会接收到通知,并自动执行相应的更新操作。这种设计的最大优势是实现了被观察者与观察者之间的解耦:两者无需了解对方的具体实现细节,仅通过统一接口进行交互。因此,在增加或移除观察者时,完全不需要修改被观察者的内部逻辑。
以家具生产为例:
核心约定:工厂需提供“注册观察者”、“移除观察者”和“通知所有观察者”的标准接口;而每个观察者则必须实现“接收并处理通知”的统一方法。
观察者模式通常由四个基本组件构成,对应到当前应用场景如下:
抽象观察者(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;
}
以下使用 C++ 编写完整的代码实现,涵盖接口定义、具体类实现以及客户端测试逻辑,并配有详细注释说明关键步骤。
notify
AbstractObserver
setProductionStatus
attach
detach
解耦能力:工厂作为被观察者,无需关心哪些具体的经销商或客户正在监听其状态,只需调用统一的通知接口即可完成广播;当需要引入新的观察者(如家装公司)时,仅需其实现指定接口并向工厂注册,无需改动工厂原有代码。
状态同步机制:一旦工厂通过特定方法更改了生产状态,系统将自动触发通知流程,确保所有已注册的观察者都能及时获得最新信息,从而避免了传统人工逐个通知的低效问题。
灵活的订阅控制:借助“注册”与“注销”功能,观察者可根据实际需求自由加入或退出监听序列,完美契合现实中“客户取消预约”或“经销商终止合作”等常见情况。
通过家具生产的案例可以看出,当系统中出现以下情形时,应优先考虑采用观察者模式:
在 C++ 开发实践中,该模式还广泛应用于图形用户界面开发(如按钮点击事件触发多个组件刷新)、日志管理系统(日志级别变更同步至多个输出终端)等场景,是一种高度实用且扩展性强的设计模式。
扫码加好友,拉您进群



收藏
