我正在考虑构建一组类来处理与各种相似但竞争的API的交互。信用卡处理就是一个很好的例子。我想要一个具有charge()
或refund()
之类的方法的类,供应用程序开发人员使用,而与商人处理器是谁无关。然后,我希望能够构建处理与特定商人处理器API交互的类。
所以我可能有一个与Stripe API交互的对象,另一个与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”值实例化该类将意味着该类在幕后将工作量传递给适当的类以处理这种交互。
我的目标是:
这是包装器类的方法,还是PHP提供了其他更有效的机制来处理这种设置?
答案 0 :(得分:1)
我将为您的内部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);
根据您的要求,您还可以使用构建器模式代替工厂来创建不同的实例。建筑商会照顾您的安装员。如果您有很多可选参数(在这里似乎不是这种情况),或者想使您的商家不可变,那么这可能会很有用。