我目前正在帮助构建一个 API,我希望第 3 方开发人员使用该 API。该 API Hook 到云中的服务。这项服务不断变化,目前还不太可靠。因此,我想在我的 SDK 中提供真实客户端和虚假客户端。每当服务出现故障时,开发人员只需使用假客户端而不是真实客户端即可继续编码。
我研究过各种设计模式,其中一些很好地解决了我的问题。但这里有一个问题......我想让代码尽可能简单:所以假设我的服务称为 Experia。我希望人们能够做这样的事情:
class Experia extends Exp
...
$ex = new Experia(/*initialization parameters*/); //init prameters like user name, password etc
$ex->story()->create($storyArgs);
目前,Experia 是一个扩展另一个类 Exp 的类,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 的初始化参数)
最佳答案
适配器模式是一个好方法。您的主要客户端是 Exp
类,开发人员使用该类与您的服务进行交互。不过,此类依赖于适配器来连接到您的服务。该适配器类需要在实例化Exp
时注入(inject),并且是必要时可以mock的部分。
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;
}
}
您还可以使用接口(interface)
规范,而不是扩展抽象
类。
对于开发人员来说,这看起来像:
$exp = new Exp(new LiveExpAdapter);
// if service is down, use instead:
// $exp = new Exp(new MockExpAdapter);
$exp->foo();
关于php - 如何使继承成为可选的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10879300/