Построение классов для абстрактной функциональности API - PullRequest
0 голосов
/ 15 апреля 2019

Я смотрю на создание набора классов для взаимодействия с различными похожими, но конкурирующими API.Хорошей иллюстрацией этого будет обработка кредитных карт.Мне нужен класс с методами типа charge() или refund(), которые использует разработчик приложения, независимо от того, кто является торговым процессором.Затем я хочу иметь возможность создавать классы, которые обрабатывают взаимодействие с конкретным API торгового процессора.

Так что у меня может быть один, который взаимодействует с API Stripe, другой для Authorize.Net и т. Д. Затем какой-томастер или класс-оболочка, который абстрагирует специфику API от разработчика приложения.

В прошлом я делал это с помощью класса-оболочки, где я создавал класс для каждого API, используя одни и те же методы (с соответствующимиВзаимодействия API), а затем класс-оболочка, который используется в приложении.Пример использования может выглядеть следующим образом:

$merchant = new Merchant( 'Stripe' );
$merchant->set_credentials( 'api_user', 'api_password' );
$merchant->set_cc( '4111-1111-1111-1111' );
$merchant->set_exp( '0121' );
$merchant->set_amount( 100.00 );
$merchant->charge();

Создание экземпляра этого класса со значением «Stripe» будет означать, что за кулисами этот класс передает рабочую нагрузку соответствующему классу для обработки этого взаимодействия.

Мои цели:

  • Абстрагировать API от разработчика приложения от необходимости знать что-либо о конкретном процессоре, кроме имени (чтобы они могли создать экземпляр класса)или необходимость внесения каких-либо изменений в код в случае изменения процессора.
  • Поскольку мне в конечном итоге потребуется поддержка большего числа торговых процессоров, я могу добавить новые классы для обработки взаимодействий с их API.

Является ли класс-оболочка способом сделать это, или PHP предоставляет другие более эффективные механизмы для обработки этого типа установки?

1 Ответ

1 голос
/ 15 апреля 2019

Я бы создал интерфейс для вашего внутреннего API, одну реализацию на внешний процессор и фабричный класс для создания правильного экземпляра.

Пример кода (PHP 7.1):

interface MerchantInterface {
    public function set_credentials(string $username, string $password);
    public function set_cc(string $number);
    public function set_exp(string $number);
    public function set_amount(float $amount);
    public function charge();
}

class StripeMerchant implements MerchantInterface {
    public function set_credentials(string $username, string $password) {}
    public function set_cc(string $number)  {}
    public function set_exp(string $number) {}
    public function set_amount(float $amount) {}
    public function charge() {}
}

class AuthorizeNetMerchant implements MerchantInterface {
    public function set_credentials(string $username, string $password) {}
    public function set_cc(string $number)  {}
    public function set_exp(string $number) {}
    public function set_amount(float $amount) {}
    public function charge() {}
}

class MerchantFactory {
    public const MERCHANT_STRIPE = 'Stripe';
    public const MERCHANT_AUTHORIZE_NET = 'Authorize.Net';

    public static function create(string $merchant): MerchantInterface {
        switch ($merchant) {
            case self::MERCHANT_STRIPE:
                return new StripeMerchant();
            case self::MERCHANT_AUTHORIZE_NET:
                return new AuthorizeNetMerchant();
            default:
                throw new Exception('Unexpected Merchant');
        }
    }
}

$stripeMerchant = MerchantFactory::create(MerchantFactory::MERCHANT_STRIPE);
$authorizeNetMerchant = MerchantFactory::create(MerchantFactory::MERCHANT_AUTHORIZE_NET);

В зависимости от ваших требований, вы можете также использовать шаблон компоновщика вместо фабрики для создания разных экземпляров.Строитель позаботится о ваших установщиках.Это может быть полезно, если у вас много необязательных параметров (здесь это не так) или вы хотите сделать своих Торговцев неизменяемыми.

...