【设计模式】其它经典模式-标记接口模式(Marker Interface Pattern)
·
标记接口模式(Marker Interface Pattern)在 C++ 中的实现
1. 模式定义
标记接口(Marker Interface)是一种不包含任何方法或数据的特殊接口,仅用于标记类的元数据信息。其主要目的是通过类型系统在编译期或运行期为类附加语义标签,实现类型检测或策略选择。
2. 核心思想
- 空接口:不声明任何成员函数(纯虚函数)。
- 类型标签:通过继承关系传递类型信息。
- 多态检测:利用
dynamic_cast或模板特化检测继承关系。
3. C++ 实现步骤(结合编译期与运行期)
步骤 1:定义标记接口
// 标记接口:可序列化
class Serializable {};
// 标记接口:线程安全
class ThreadSafe {};
步骤 2:实现具体类
class Document : public Serializable {
public:
void save() const { std::cout << "Saving document...\n"; }
};
class Logger : public Serializable, public ThreadSafe {
public:
void log() { std::cout << "Logging thread-safe...\n"; }
};
class Calculator { // 无任何标记
public:
void compute() { std::cout << "Computing...\n"; }
};
步骤 3:利用标记进行逻辑控制
方式 1:运行期检测(dynamic_cast)
void processObject(void* obj) {
// 检测是否可序列化
if (auto* serializable = dynamic_cast<Serializable*>(static_cast<Object*>(obj))) {
std::cout << "Object is serializable\n";
// 安全调用具体类方法(需向下转型)
if (auto* doc = dynamic_cast<Document*>(serializable)) {
doc->save();
}
}
// 检测是否线程安全
if (dynamic_cast<ThreadSafe*>(static_cast<Object*>(obj))) {
std::cout << "Object is thread-safe\n";
}
}
方式 2:编译期检测(模板 + SFINAE)
// 利用 std::is_base_of 进行类型特征检查
template <typename T>
void serializeIfPossible(const T& obj) {
if constexpr (std::is_base_of_v<Serializable, T>) {
std::cout << "Serializing: ";
obj.save(); // 直接调用,编译期安全检查
} else {
std::cout << "Cannot serialize this type\n";
}
}
4. 完整代码示例
#include <iostream>
#include <type_traits>
// 标记接口定义
class Serializable {};
class ThreadSafe {};
// 具体类实现
class Document : public Serializable {
public:
void save() const { std::cout << "Document saved.\n"; }
};
class Logger : public Serializable, public ThreadSafe {
public:
void log() const { std::cout << "Logging safely.\n"; }
};
class Calculator { // 无标记
public:
void compute() const { std::cout << "Computing...\n"; }
};
// 编译期处理(模板元编程)
template <typename T>
void process(const T& obj) {
obj.compute(); // 所有类型通用操作
if constexpr (std::is_base_of_v<Serializable, T>) {
std::cout << ">> Serializing: ";
obj.save();
}
if constexpr (std::is_base_of_v<ThreadSafe, T>) {
std::cout << ">> Thread-safe operation: ";
obj.log();
}
}
int main() {
Document doc;
Logger logger;
Calculator calc;
// 编译期分派
process(doc); // 输出序列化
process(logger); // 输出序列化和线程安全
process(calc); // 仅输出计算
return 0;
}
5. 输出结果
Computing...
>> Serializing: Document saved.
Computing...
>> Serializing: Logging safely.
>> Thread-safe operation: Logging safely.
Computing...
6. 关键优势
- 类型安全:编译期检测避免运行时错误。
- 解耦:业务逻辑与标记接口分离,符合开闭原则。
- 灵活扩展:新增标记无需修改已有类(如添加
Cloneable接口)。 - 多态增强:配合
dynamic_cast实现运行时分派。
7. 适用场景
- 需要为类附加元数据(如序列化、线程安全)。
- 策略模式中根据不同标记选择不同算法。
- 框架中自动识别组件特性(如 ORM 中的持久化标记)。
8. 对比其他技术
| 技术 | 优势 | 劣势 |
|---|---|---|
| 标记接口 | 类型安全,编译期优化 | 需继承(可能受限于单继承) |
| 属性(C#/Java) | 无需继承,可附加任意元数据 | C++ 原生不支持 |
| 枚举 + 变量 | 简单直观 | 缺乏类型约束,易出错 |
推荐阅读
更多推荐



所有评论(0)