7

我知道在 PHP 中链接的好处,但可以说我们有以下情况

$Mail = new MailClass("mail")
        ->SetFrom("X")
        ->SetTo("X")
        ->SetSubject("X")
        ->AddRecipient("X")
        ->AddRecipient("X")
        ->AddRecipient("X")
        ->AddRecipient("X")
        ->AddRecipient("X")
        ->AddRecipient("X")
        ->Send();

一遍又一遍地返回和重用对象是否有任何问题,例如速度或未能遵循最佳实践等问题

如果您是 Fluent-Interface 的新手,也可以好好阅读:Martin Fowler on Fluent-Interfaces

我完全理解它不必这种方式编程,并且可以像这样处理:

$Mail = new MailClass("mail");
$Mail->AddRecipien(
    array(/*.....*/)
);
$Mail->SetFrom("X");
$Mail->SetTo("X");
$Mail->SetSubject("X");
$Mail->Send();

但可以说我有一个像这样的对象:

$Order = new Order()
         ->With(22,'TAL')
         ->With(38,'HPK')->Skippable()
         ->With(2,'LGV')
         ->Priority();

请注意->With(38,'HPK')->Skippable(),这是此类编程的 Pro 的完美示例

4

4 回答 4

5

如果您必须验证某事,我认为在 AddRecipient 方法本身中验证它更有意义,但性能应该大致相同。而且我不知道使用方法链接的任何一般缺点。

于 2010-09-29T13:01:50.457 回答
2

你不能从类实例化直接链条:

$Mail = new MailClass("mail") 
            ->SetFrom("X")
            ->SetTo("Y");

您必须先实例化,然后将链断针对实例化对象:

$Mail = new MailClass("mail") ;
$Mail->SetFrom("X")
     ->SetTo("Y");

如果您在各个 setter 方法中进行验证(您应该这样做),那么您需要确保在遇到验证错误时抛出异常。您不能简单地在错误时返回布尔值 false,否则链接将尝试针对布尔值而不是您的类实例调用下一个方法,您将得到。

致命错误:在第 23 行的 C:\xampp\htdocs\oChainTest.php 中的非对象上调用成员函数 SetSubject()

如果你抛出异常,你可以将链包裹在 try...catch

$Mail = new MailClass("mail");
try {
    $Mail->SetFrom("X")
        ->SetTo("Y")
        ->SetSubject("Z");
} catch (Exception $e) {
    echo $e->getMessage();
}

但作为警告,这将使实例处于部分更新的状态,对于成功验证/执行的方法没有回滚(除非您自己编写),并且不会调用异常之后的方法。

于 2010-09-29T13:47:45.400 回答
1

编辑:更新答案以匹配问题
函数调用比循环慢,例如,与调用采用数组然后在循环中处理的方法addRecipient()相比,链接该方法会稍微降低性能。addRecipients()

此外,链接到流式 API 的更复杂的方法可能需要额外记录与上次调用的方法相关的数据,以便下一次调用可以继续处理该数据,因为所有方法都返回构建链的相同对象。让我们看一下您的示例:

...
->With(22, 'TAL')
->With(38, 'HPK')->Skippable()
->With(2, 'LGV')
...

这需要你记住Skippable()是应用于(38, 'HPK')而不是(22, 'TAL').

您几乎不会注意到性能损失,除非您的代码将在循环中被非常频繁地调用,或者当您对 Web 服务器有如此多的并发请求以至于它接近其限制时(这是重负载网站的情况) .

另一方面是方法链接模式强制使用异常来表示错误(我并不是说这是一件坏事,它只是不同于经典的“调用和检查函数结果”编码风格)。

然而,通常会有一些函数产生其他值而不是它们所属的对象(例如那些返回对象和访问器状态的函数)。重要的是,您的 API 的用户可以确定哪些函数是可链接的,哪些函数是可链接的,而不必在每次遇到新方法时参考文档(例如,说明所有 mutators 且只有 mutators 支持链接的指南)。


回答原来的问题:

[...] 我遇到的链接问题是您无法真正执行额外的验证 [...]

或者,实现一个您在设置所有属性后调用的专用验证方法,并让它返回一个验证失败数组(可以是纯字符串或对象,例如 named ValidationFailure)。

于 2010-09-29T13:06:23.677 回答
0

这是一把双刃剑。

好的一面?这比重新解决课程,这是清洁的,虽然它主要只是一个语法改变,但它将加快处理一点。优选的是循环这种链子而不是在长form中循环每个呼叫。

糟糕的一面?当人们先习惯它时,这将导致安全问题。在你的进入vars的净化方面努力,所以你不会在那里传递一些东西。不要过度复杂化你的课程。

  1. 预验证您的信息。
  2. 预授权您的用户。

在循环中,将这些方法链接到循环中,我看不到问题。

于 2010-09-29T13:09:17.647 回答