2012-06-04 5 views
2

Я в настоящее время помогаю построить 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, который содержит список этих ресурсов и файлов, которые они доступны в .. и это тоже расширяет общий класс, называемый клиент, который определяет основные Get() и пост() методы и т.д., и в основном устанавливает клиент удаленного 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 или Fake в зависимости от его декларации, без какого-либо уродства. И уродством я имею в виду любой дополнительный код, который разработчикам, использующим мой API, придется использовать. Так, например, одна вещь, которую я пытался сделать, отщепляются клиент из опыта и в основном это сделать

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

, но тогда проблема заключалась в том, что каждый раз, когда я хотел использовать назвать ресурс .. Я должен был указать клиенту:

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

клиентская часть является дополнительным кодом, который я не могу включить в моем апи ..

так долго короткая история .. что шаблон проектирования (или прямой путь, если это возможно .. в PHP), который достигает такой же результат, как выборочное наследование от одного класса

так как иметь возможность делать это:

класс Experia проходит (либо Exp или ExpFake в зависимости от параметров инициализации EXPERIA в)

+0

Возможно, вам придется расширять 'ExpFake'' Exp' вместо 'Client' и переопределять все, что необходимо фактическое обслуживание. – lanzz

+0

@lanzz, который до сих пор не отвечает на мой вопрос .. что будет дальше в этом случае Experia? ExpFake или Exp? это та же проблема – abbood

ответ

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(); 
+0

выглядит неплохо .. я буду реализовывать это и посмотреть, если какой-либо хотча скачок на меня .. – abbood

0

зависит от версии PHP, но я хотел бы использовать черты, в этом случае

trait Exp { 

} 
trait ExpFake { 

}  
class Experia { 
    use Exp; 
} 

альтернатива с драйверами нормально, а, например, определить интерфейс и отдельные драйверы или реализации (как в случае с db, когда у вас есть разные классы драйверов, например, mysql, psql и т. д.)

+0

к сожалению, php 5.4 [используется] (http://w3techs.com/technologies/details/pl-php/ 5/все) менее чем на 1%. Не идеальное решение для API, которое будет использоваться разработчиками всех сорта – abbood

+0

, это зависит от вашей клиентской базы. решение для драйверов является альтернативой. – jancha

Смежные вопросы