如何使继承可选

时间:2012-06-04 09:45:49

标签: php oop inheritance

我目前正在帮助构建一个我希望第三方开发人员使用的API。此API挂钩到云中的服务。这项服务不断变化,目前还不太可靠。因此,我想在我的SDK中提供真实客户端和虚假客户端。每当服务停止时,开发人员可以简单地使用虚假客户端而不是真实客户端并继续编码。

我看过各种各样的设计模式,有些很好地解决了我的问题。虽然这是一个问题。我想让代码变得尽可能简单:所以让我们说我的服务名为Experia。我希望人们能够做到这样的事情:

class Experia extends Exp

...

$ex = new Experia(/*initialization parameters*/);  //init prameters like user name, password etc
$ex->story()->create($storyArgs);

目前,Experia是一个扩展另一个类Exp的类,它包含这些资源的列表以及它们可用的文件..它还扩展了一个名为Client的泛型类,它定义了基本的get()和post()方法等,基本上设置客户端远程URL等等(它包裹着pest library

所以Exp就是这样的:

class Exp extends Client
{     
    public function story() {
         include_once('classes/User.php');
    }

    //other resource methods

}

我想创建另一个包含所有虚假资源的类。这样的事情:

class ExpFake extends Client
{     
    public function story() {
         include_once('classesFake/User.php');
    }

    //other resource methods

}

这是我面临的问题。我希望Experia能够扩展Exp或ExpFake,具体取决于它的声明,没有任何丑陋..而且丑陋是指使用我的API的开发人员必须使用的任何额外代码。因此,举例来说,我尝试做的一件事就是将客户端与Exp分离,基本上就是这样做

$ex = new Experia(/*... */);
$ex->client = new fakeClient();   //I could also do $ex-> client = new realClient();

但问题是,每次我想使用调用资源时......我必须指定客户端:

$this->client->story()->create($args)

客户端部分是我无法包含在我的api中的额外代码..

这么长的故事简短..什么是设计模式(或者直接方式,如果可能的话......在php中),它实现了与从一个类或另一个类中有选择地继承相同的结果

所以可以选择这样做:

类Experia扩展(Exp或ExpFake取决于Experia的初始化参数)

2 个答案:

答案 0 :(得分:2)

一个好方法是适配器模式。您的主要客户端是Exp类,开发人员使用该类与您的服务进行交互。此类依赖于连接到您的服务的适配器。在实例化Exp时需要注入此适配器类,并且必要时可以模拟该部分。

class Exp {

    protected $adapter;

    public function __construct(ExpAdapter $adapter) {
        $this->adapter = $adapter;
    }

    public function foo() {
        return $this->adapter->doFoo();
    }

}

abstract class ExpAdapter {

    abstract public function doFoo();

}

然后,您可以创建一个真实的ExpAdapter和一个模拟的:

class LiveExpAdapter extends ExpAdapter {

    public function doFoo() {
        // contact the actual service
    }

}

class MockExpAdapter extends ExpAdapter {

    public function doFoo() {
        return true;
    }

}

您也可以使用abstract规范,而不是扩展interface类。

对于开发人员来说,这将是:

$exp = new Exp(new LiveExpAdapter);
// if service is down, use instead:
// $exp = new Exp(new MockExpAdapter);

$exp->foo();

答案 1 :(得分:0)

取决于你的php版本,但我会使用traits,在这种情况下

trait Exp {

}
trait ExpFake {

}    
class Experia {
    use Exp;
}

替代驱动程序也很好,例如定义接口和单独的驱动程序或实现(与db一样,当你有不同的驱动程序类,例如mysql,psql等)