Ser*_* K. 22 c++ design-patterns delegation method-chaining chaining
这绝对是主观的,但我想尽量避免它变得有争议.我认为如果人们适当地对待它可能是一个有趣的问题.
在我最近的几个项目中,我曾经实现过长代理链是常见的架构.
可能经常遇到双重委托链:
bool Exists = Env->FileSystem->FileExists( "foo.txt" );
Run Code Online (Sandbox Code Playgroud)
三重代表团并不罕见:
Env->Renderer->GetCanvas()->TextStr( ... );
Run Code Online (Sandbox Code Playgroud)
存在更高级别的代表团,但实际上很少.
在上述示例中,不执行NULL运行时检查,因为所使用的对象始终存在并且对于程序的运行是至关重要的并且在执行开始时被显式构造.基本上我曾经在这些情况下拆分委托链:
1)我重用通过委托链获得的对象:
{ // make C invisible to the parent scope
clCanvas* C = Env->Renderer->GetCanvas();
C->TextStr( ... );
C->TextStr( ... );
C->TextStr( ... );
}
Run Code Online (Sandbox Code Playgroud)
2)在使用之前,应该检查委托链中间某处的中间对象是否为NULL.例如.
clCanvas* C = Env->Renderer->GetCanvas();
if ( C ) C->TextStr( ... );
Run Code Online (Sandbox Code Playgroud)
我曾经通过提供代理对象来对抗案例(2),以便可以在非NULL对象上调用方法,从而产生empty结果.
我的问题是:
以下是我在做出选择时考虑的一些优缺点:
优点:
缺点:
我想知道长代表团的其他利弊.请根据有争议的观点提出你的推理和投票,而不是你对它的看法.
bit*_*ask 14
我不会到目前为止称为反模式.但是,第一个缺点C是即使在逻辑相关(太过无端的范围)之后,您的变量也是可见的.
您可以使用以下语法解决此问题:
if (clCanvas* C = Env->Renderer->GetCanvas()) {
C->TextStr( ... );
/* some more things with C */
}
Run Code Online (Sandbox Code Playgroud)
这在C++中是允许的(虽然它不在C中)并且允许您保持适当的范围(C作用域,就好像它在条件的块内)并检查NULL.
断言某事不是NULL绝不会比被SegFault杀死更好.所以我不建议简单地跳过这些检查,除非你100%确定该指针永远不会是NULL.
此外,如果您觉得特别花哨,您可以将支票封装在一个额外的免费功能中:
template <typename T>
T notNULL(T value) {
assert(value);
return value;
}
// e.g.
notNULL(notNULL(Env)->Renderer->GetCanvas())->TextStr();
Run Code Online (Sandbox Code Playgroud)
根据我的经验,像这样的链条通常包含不那么微不足道的吸气剂,导致效率低下.我认为(1)是一种合理的方法.使用代理对象似乎有点矫枉过正.我宁愿看到NULL指针崩溃而不是使用代理对象.