【设计模式】其它经典模式-空对象模式(Null Object Pattern)
空对象模式(Null Object Pattern)(C++ 示例)
模式核心思想
用行为合理的空对象替代 nullptr
检查,消除客户端代码中的判空逻辑,避免空指针异常,提供默认的安全行为。
模式结构
-
抽象接口 (AbstractObject)
定义客户端依赖的通用接口 -
真实对象 (RealObject)
实现具体业务逻辑 -
空对象 (NullObject)
实现无操作的默认行为(安全替代品) -
客户端 (Client)
通过抽象接口操作对象,无需判空
C++ 实现示例
场景描述
实现一个日志系统,当未配置日志器时使用安全的空日志器,避免客户端判空。
代码实现
#include <iostream>
#include <string>
#include <memory>
// 1. 抽象接口
class ILogger {
public:
virtual void log(const std::string& message) = 0;
virtual ~ILogger() = default;
};
// 2. 真实对象
class ConsoleLogger : public ILogger {
public:
void log(const std::string& message) override {
std::cout << "[LOG] " << message << std::endl;
}
};
// 3. 空对象(关键实现)
class NullLogger : public ILogger {
public:
void log(const std::string&) override {
// 安全无操作(替代nullptr)
}
};
// 4. 对象工厂(封装空对象创建)
class LoggerFactory {
public:
static std::unique_ptr<ILogger> createLogger(bool enableLogging) {
if (enableLogging) {
return std::make_unique<ConsoleLogger>();
}
return std::make_unique<NullLogger>(); // 返回空对象而非nullptr
}
};
// 5. 客户端代码(无判空逻辑)
void processTransaction(int amount, ILogger& logger) {
logger.log("Transaction started");
// 业务逻辑...
logger.log("Processed amount: " + std::to_string(amount));
}
int main() {
auto logger = LoggerFactory::createLogger(false); // 关闭日志
// 安全调用(无需检查nullptr)
processTransaction(100, *logger);
// 启用真实日志
auto activeLogger = LoggerFactory::createLogger(true);
processTransaction(200, *activeLogger);
}
关键输出
[LOG] Transaction started
[LOG] Processed amount: 200
模式优势
-
消除判空检查
客户端代码不再需要if(logger != nullptr)
防御性检查 -
防止空指针崩溃
空对象提供安全默认行为 -
简化客户端代码
业务逻辑更清晰,专注核心流程 -
符合开闭原则
新增日志类型不影响客户端 -
明确表达空语义
比返回nullptr
更具表达力
适用场景
- 需要安全替代
nullptr
的场合 - 客户端不应处理对象缺失逻辑时
- 系统存在大量判空检查时
- 需要提供默认无操作行为时
重要提示:当对象缺失是严重错误时(需显式处理),不适合使用此模式。
推荐阅读
上一篇: 几秒钟就充满电!科学
下一篇: 暂无数据