2

我的应用程序中有一个 SystemInfoFactory 类,它有一个getSystemInfo()方法:

/**
 * Returns SystemInfo object based on which OS
 * server uses
 *
 * @return SystemInfoInterface SystemInfo object
 */
public function getSystemInfo()
{
    $os = $this->getOS();

    $systemInfo = null;

    switch ($os) {
        case "Linux":
            $systemInfo = new LinuxInfo();
            break;
        case "Darwin":
            $systemInfo = new OSXInfo();
            break;
        case "Windows":
            $systemInfo = new WindowsInfo();
            break;
    }
    return $systemInfo;
}

因此它根据主机系统选择合适的对象。现在,每个“信息类”都实现SystemInfo了接口(getArchitecture、getCPU 等方法),但正如您所见,我的代码中没有任何地方检查返回的对象是否真的实现了接口。$systemInfo在返回之前检查所选对象是否实现它是否被认为是“好习惯” ?这显然不是必需的,但如果有人扩展此应用程序(例如添加 BSD 支持)并忘记实现所有方法,他可能更难以调试。

4

2 回答 2

2

这绝对是个好习惯。您在 docblock 中定义您的方法返回SystemInfo. 您的来电者应该能够依赖它。这在您的代码中很简单:

/**
 * Returns SystemInfo object based on which OS
 * server uses
 *
 * @return SystemInfoInterface SystemInfo object
 */
public function getSystemInfo()
{
    $os = $this->getOS();

    $systemInfo = null;

    switch ($os) {
        case "Linux":
            $systemInfo = new LinuxInfo();
            break;
        case "Darwin":
            $systemInfo = new OSXInfo();
            break;
        case "Windows":
            $systemInfo = new WindowsInfo();
            break;
        default:
            throw new \RuntimeException('System not supported');
            break;
    }

    if (!$systeminfo instanceof SystemInfo) {
        throw new \RuntimeException('Invalid SystemInfo object returned');
    }

    return $systemInfo;
}

确保您声明您将从该方法调用中抛出异常。这里的异常清楚地说明了发生了什么,而不必稍后在代码中追逐“未定义的方法”错误。

于 2013-03-05T14:16:42.723 回答
1

我想,这里的关键词是 Duck Typing。一个对象的接口是由它的方法和属性定义的,而不是它的祖先和实现的接口。

看看这个:http ://en.wikipedia.org/wiki/Duck_typing

回到 PHP:如果你不检查对象是否实现了你的接口,它是完全有效的并且没有坏的风格。如果代码崩溃,则必须责怪该类的实现者。如果代码弄乱了,我会觉得很烦人if ($obj instanceof FancyInterface) {

于 2013-03-05T14:21:09.430 回答