我目前正在帮助构建一个我希望第三方开发人员使用的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的初始化参数)
答案 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等)