Php 如何使继承成为可选的
我目前正在帮助构建一个希望第三方开发者使用的API。此API与云中的服务挂钩。这项服务不断变化,目前不是很可靠。因此,我想在我的SDK中提供真实的客户端和假的客户端。每当服务关闭时,开发人员就可以简单地使用假客户端而不是真客户端继续编码 我研究了各种设计模式,其中一些很好地解决了我的问题。不过,这里有个陷阱。。我想让代码尽可能简单:所以让我们假设我的服务叫做Experia。我希望人们能够这样做:Php 如何使继承成为可选的,php,oop,inheritance,Php,Oop,Inheritance,我目前正在帮助构建一个希望第三方开发者使用的API。此API与云中的服务挂钩。这项服务不断变化,目前不是很可靠。因此,我想在我的SDK中提供真实的客户端和假的客户端。每当服务关闭时,开发人员就可以简单地使用假客户端而不是真客户端继续编码 我研究了各种设计模式,其中一些很好地解决了我的问题。不过,这里有个陷阱。。我想让代码尽可能简单:所以让我们假设我的服务叫做Experia。我希望人们能够这样做: class Experia extends Exp ... $ex = new Experia(
class Experia extends Exp
...
$ex = new Experia(/*initialization parameters*/); //init prameters like user name, password etc
$ex->story()->create($storyArgs);
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的类,该类包含这些资源及其可用文件的列表。。它还扩展了一个名为Client的泛型类,该类定义了基本的get()和post()方法等,并基本上设置了客户端远程url等(它围绕
Exp是这样的:
class Experia extends Exp
...
$ex = new Experia(/*initialization parameters*/); //init prameters like user name, password etc
$ex->story()->create($storyArgs);
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
}
我想创建另一个包含我所有伪资源的类。。大概是这样的:
class Experia extends Exp
...
$ex = new Experia(/*initialization parameters*/); //init prameters like user name, password etc
$ex->story()->create($storyArgs);
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
时,需要注入此适配器类,如果需要,它是可以模拟的部分
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;
}
}
除了扩展抽象类
之外,还可以使用接口
规范
对于开发人员来说,这看起来像:
$exp = new Exp(new LiveExpAdapter);
// if service is down, use instead:
// $exp = new Exp(new MockExpAdapter);
$exp->foo();
取决于您的php版本,但在这种情况下,我会使用traits
trait Exp {
}
trait ExpFake {
}
class Experia {
use Exp;
}
驱动程序的替代方案也可以,例如定义接口和单独的驱动程序或实现(与db一样,当您有不同的驱动程序类,例如mysql、psql等)您可能应该让
ExpFake
扩展Exp
,而不是客户端,并覆盖所有需要实际服务的内容。@lanzz仍然没有回答我的问题。。在这种情况下,Experia将扩展什么?Exp是假的还是Exp?这是同样的问题不幸的是,PHP5.4不到1%。。对于所有sortsa开发人员都将使用的API来说,这不是一个理想的解决方案。当然,这取决于您的客户群。驱动程序解决方案是另一种选择。