c++ - 是否有更好的实现来处理开关?
问题描述
我有一个名为回复的类类型,它的形式如下:
class reply {
public:
enum class type {
error = 0,
bulk_string = 1,
simple_string = 2,
null = 3,
integer = 4,
array = 5
};
public:
type get_type(void) const {
return type_;
}
private:
type type_;
};
回复实例将由其他函数返回,因此我将通过探测 get_type 调用的每个可能值来处理回复。第一个解决方案是使用 switch case,但我想使用“OOP”思想来封装它,如下所示:
template<typename Handlers, typename Handlers::type*...types>
class handlers {
private:
static constexpr typename Handlers::type* dealers[] = { types... };
public:
static void deal(const reply& reply) {
dealers[int(reply.get_type())](reply);
}
};
template<typename Handlers>
class handle{
public:
using handles = handlers<Handlers, Handlers::error_handle,
Handlers::bulk_string_handle, Handlers::simple_string_handle,
Handlers::null_handle, Handlers::integer_handle,
Handlers::array_handle>;
};
class handler
{
public:
static void error_handle(const reply&) {
std::cout << "error_handle" << std::endl;
}
static void bulk_string_handle(const reply&) {
std::cout << "bulk_string_handle" << std::endl;
}
static void simple_string_handle(const reply&) {
std::cout << "simple_string_handle" << std::endl;
}
static void null_handle(const reply&) {
std::cout << "null_handle" << std::endl;
}
static void integer_handle(const reply&) {
std::cout << "integer_handle" << std::endl;
}
static void array_handle(const reply&) {
std::cout << "array_handle" << std::endl;
}
public:
using type = decltype(error_handle);
using handles = handle<handler>::handles;
};
最后,我可以这样处理回复:
int main()
{
reply rep;
handler::handles::deal(rep);
return 0;
}
注意:每个回复都有其处理程序。我关注的是是否有更好的方法来适应解决方案?
解决方案
尽可能设计至少“中心点”。专注于使添加新回复类型变得容易,设计将基于该假设。使用选择处理程序的单个中心点创建与每个回复相关联的分离部分。中心点称为工厂,小部件实现相同的接口。
struct handler {
// I do not know, maybe this should store the reply?
// No idea.
virtual void handle(const reply&);
virtual ~handler();
};
struct error_handler : handler {
void handle(const reply&) { /* blabla */ }
handler construct() { return error_handler(); }
};
/* etc. for each handle type */
// TODO: convert to static array to save dynamic allocatiosn
std::map<std::reply::type, std::function<handler()>> handlers_map{
{ std::reply::error, []() { return error_handler(); } },
/* etc. for each handle type */
};
handler handler_factor(const reply& r) {
return handlers_map.at(r.get_type())();
}
#if YAY_AN_ARRAY // an example of converting map to a static array
// TODO: do it as a member function
static handler error_handler_construct() { return error_handler(); }
static std::array<handler (*)(), 1> handlers_array{
&error_handler_construct,
/* etc. */
};
handler handler_factor(const reply &r) {
// remember about error handling
return handlers_array.at(
static_cast<int>(r.get_type())
)();
}
#elif YAY_ANOTHER_ARRAY
static handler (*const handlers_array[])() = {
[static_cast<int>(reply::type::error)] = &error_handler_construct,
/* etc. */
};
handler handler_factor(const reply &r) {
auto t = static_cast<int>(r.get_type();
if (t < 0 || t > sizeof(handlers_array)/sizeof(*handlers_array)) {
abort();
}
return handlers_array[t]();
}
#enidf
int main() {
reply rep;
auto h = handler_factor(rep);
h.handle(rep);
return 0;
}
推荐阅读
- amazon-web-services - 如何配置亚马逊队列服务消费计数
- php - 获取SQL数据时PHP未识别索引
- python - 如何使用 pandas 或 numpy 计算真阳性的出现?
- python - 如何使用 Python REST API 从 TRTH/datascope 下载深度数据?
- javascript - 鉴于浏览器被限制为 6 个并发连接,XmlHttpRequest 在队列中等待时是否会超时?
- c++ - c++数组使用for循环输出降雨统计
- amazon-ec2 - 通过 cft 顺序初始化 ec2
- python - 根据列表中数字之一的位置查找排列列表中的数字
- presto - Presto 工作进程在某个时候神秘地杀死并重新启动
- android - 使用 Dagger2 为 AndroidX 片段提供注入?