【问题标题】:PHP - Using empty interfaces to determine logicPHP - 使用空接口来确定逻辑
【发布时间】:2012-10-03 18:46:49
【问题描述】:

在一些地方,我根据类实现的接口执行逻辑 - 是否有任何理由表明这可能是错误的,也可能不是错误的? (感觉很脏)

这样做的原因是您不必添加任何类属性或方法来确定这些事情,基本上在类定义中您可以明确说明它可以/不能做什么。

一个用例是 ajax 调用,有些需要您登录,有些则不需要:

class ajax_ads extends ajax_controller implements no_login {

}

另外,接口中没有方法,仅用于此目的。

interface no_login {}

然后在基本控制器中:

$controller = controller::factory()
if( !($controller instanceof no_login) && !$controller->LoggedIn()){
    return $controller->redirect(/*login page*/); 
}

instance_of 使用起来看起来轻巧简单,而且效果很好,但我又觉得我完全滥用了界面的目的。

所以我问,使用接口来确定逻辑是一个坏主意、坏 oop 还是“好的”?

【问题讨论】:

  • 我的第一反应是说这是错误的,但我需要一点时间来想一个好的理由。

标签: php oop interface


【解决方案1】:

当您需要ifswitch 来确定对象应该处于的状态时,通常表明您需要多态性

在您的情况下,应该有一个 abstract 类:Ajax_Ads,以及两个扩展类:No_Login_Ajax_Ads extends Ajax_AdsLogin_Ajax_Ads extends Ajax_Ads。然后你根据程序的状态实例化你需要的那个,这可以通过 factory 来完成。

欲了解更多信息,请观看以下讲座:The Clean Code Talks -- Inheritance, Polymorphism, & Testing

【讨论】:

  • 啊是的,那是it
  • 这是有道理的。如果我创建了一个确定登录属性的中间类怎么办? ajax_controller -> ajax_no_login -> ajax_ads 或 ajax_controller -> ajax_login -> ajax_ads。这样我就可以在我所有的 ajax 控制器中重用。 (注意大多数总是全部登录或全部未登录)
  • @Aknosis:观看本讲座了解更多详情。一个真正的大开眼界(我推荐这个家伙的所有关于 OOP 的视频)。 youtube.com/watch?v=4F72VULWFvc
【解决方案2】:

接受的答案来自 2012 年。Laravel 今天使用空接口模式,所以我会说没关系。

<?php

namespace Illuminate\Contracts\Queue;

interface ShouldQueue
{
    //
}

https://github.com/laravel/framework/blob/8.x/src/Illuminate/Contracts/Queue/ShouldQueue.php

protected function sendMailable(MailableContract $mailable)
{
    return $mailable instanceof ShouldQueue
                    ? $mailable->mailer($this->name)->queue($this->queue)
                    : $mailable->mailer($this->name)->send($this);
}

https://github.com/laravel/framework/blob/8.x/src/Illuminate/Mail/Mailer.php#L300(第 300-305 行)

【讨论】:

    【解决方案3】:

    我不知道有什么缺点,但感觉就像是对接口语法的误用。为什么不在 ajax_ads 中实现一个简单的方法:

    class ajax_ads
    {
        ...
        public function requiresLogin() { return false; }
    }
    

    然后替换

    if ($controller instanceof no_login) ...
    

    通过

    if (!$controller->requiresLogin()) ...
    

    这种方法可以缩短到与trait 几乎相同的简洁程度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-27
      • 2016-02-11
      • 2016-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-08
      相关资源
      最近更新 更多