feat : Bridge pay

This commit is contained in:
2025-09-07 18:22:41 +08:00
parent cb7e8842d6
commit 33cd767477
11 changed files with 369 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace App\Controller\Test;
use App\Service\Test\Bridge\PayService;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping;
#[Controller(prefix: 'bridge/test')]
class BridgeController
{
/**
* 桥接消费
* @return array
*/
#[RequestMapping(path: 'pay', methods: 'GET')]
public function pay(): array
{
return (new PayService)->handle();
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace App\Interface\Test\Bridge;
interface PaymentInterface
{
/**
* @param float $amount
* @return array
*/
public function pay(float $amount): array;
/**
* @param float $amount
* @return array
*/
public function refund(float $amount): array;
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
* @web_site https://ctexthuang.com
*/
declare(strict_types=1);
namespace App\Service\Test\Bridge\Pay\Lib;
use App\Interface\Test\Bridge\PaymentInterface;
class AlipayPayment implements PaymentInterface
{
/**
* @param float $amount
* @return array
*/
public function pay(float $amount): array
{
return [
'type' => 'pay',
'price' => $amount,
'pay_type' => 'alipay',
'msg' => 'Processing credit card payment of ' . $amount . PHP_EOL,
];
}
/**
* @param float $amount
* @return array
*/
public function refund(float $amount): array
{
return [
'type' => 'refund',
'price' => $amount,
'pay_type' => 'alipay',
'msg' => 'Processing credit card refund of ' . $amount . PHP_EOL,
];
}
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
* @web_site https://ctexthuang.com
*/
declare(strict_types=1);
namespace App\Service\Test\Bridge\Pay\Lib;
use App\Interface\Test\Bridge\PaymentInterface;
class CreditCardPayment implements PaymentInterface
{
/**
* @param float $amount
* @return array
*/
public function pay(float $amount): array
{
return [
'type' => 'pay',
'price' => $amount,
'pay_type' => 'credit_card',
'msg' => 'Processing credit card payment of ' . $amount . PHP_EOL,
];
}
/**
* @param float $amount
* @return array
*/
public function refund(float $amount): array
{
return [
'type' => 'refund',
'price' => $amount,
'pay_type' => 'credit_card',
'msg' => 'Processing credit card refund of ' . $amount . PHP_EOL,
];
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
* @web_site https://ctexthuang.com
*/
declare(strict_types=1);
namespace App\Service\Test\Bridge\Pay;
use App\Interface\Test\Bridge\PaymentInterface;
use App\Interface\Test\Decorator\LoggerInterface;
abstract class PaymentGateway
{
/**
* @var PaymentInterface
*/
protected PaymentInterface $payment;
/**
* @var LoggerInterface
*/
protected LoggerInterface $logger;
/**
* 构造函数
* @param PaymentInterface $payment
* @param LoggerInterface $logger
*/
public function __construct(PaymentInterface $payment, LoggerInterface $logger)
{
$this->payment = $payment;
$this->logger = $logger;
}
/**
* 抽象支付类
* @param float $amount
* @return array
*/
abstract public function processPayment(float $amount): array;
/**
* 抽象退款类
* @param float $amount
* @return array
*/
abstract public function processRefund(float $amount): array;
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
* @web_site https://ctexthuang.com
*/
declare(strict_types=1);
namespace App\Service\Test\Bridge\Pay;
class PremiumPaymentService extends PaymentGateway
{
/**
* @param float $amount
* @return array
*/
public function processPayment(float $amount): array
{
$fee = $amount * 0.02; // 2%手续费
$this->logger->debug('Premium payment processing with fee: ' . $fee);
return $this->payment->pay($amount + $fee);
}
/**
* @param float $amount
* @return array
*/
public function processRefund(float $amount): array
{
$fee = $amount * 0.01; // 1%手续费
$this->logger->debug('Premium payment processing with refund: ' . $fee);
return $this->payment->refund($amount - $fee);
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
* @web_site https://ctexthuang.com
*/
declare(strict_types=1);
namespace App\Service\Test\Bridge\Pay;
class StandardPaymentService extends PaymentGateway
{
/**
* @param float $amount
* @return array
*/
public function processPayment(float $amount): array
{
$this->logger->debug('Standard payment processing');
return $this->payment->pay($amount);
}
/**
* @param float $amount
* @return array
*/
public function processRefund(float $amount): array
{
$this->logger->debug('Standard refund processing');
return $this->payment->refund($amount);
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
* @web_site https://ctexthuang.com
*/
declare(strict_types=1);
namespace App\Service\Test\Bridge;
use App\Service\Test\Bridge\Pay\PaymentGateway;
use App\Service\Test\TestBaseService;
use Hyperf\Di\Annotation\Inject;
class PayService extends TestBaseService
{
/**
* @var PaymentGateway
*/
#[Inject('standard_payment')]
protected PaymentGateway $standardPaymentGateway;
/**
* @var PaymentGateway
*/
#[Inject('premium_payment')]
protected PaymentGateway $premiumPaymentGateway;
/**
* @return array
*/
public function handle(): array
{
$amount = $this->request->input('amount',100);
$type = $this->request->input('type','standard');
$payment = $type === 'premium' ? $this->premiumPaymentGateway : $this->standardPaymentGateway;
$payRes = $payment->processPayment($amount);
$refundRes = $payment->processRefund($amount);
$refundPreRes = $this->premiumPaymentGateway->processRefund($amount);
$payPreRes = $this->premiumPaymentGateway->processPayment($amount);
return $this->return->success('success',[
'pay_res' => $payRes,
'refund_res' => $refundRes,
'refund_pre_res' => $refundPreRes,
'pay_pre_res' => $payPreRes,
]);
}
}

View File

@@ -11,11 +11,16 @@ declare(strict_types=1);
*/ */
use App\Interface\Test\Adapter\CacheInterface; use App\Interface\Test\Adapter\CacheInterface;
use App\Interface\Test\Bridge\PaymentInterface;
use App\Interface\Test\Decorator\HttpClientInterface; use App\Interface\Test\Decorator\HttpClientInterface;
use App\Interface\Test\Decorator\LoggerInterface; use App\Interface\Test\Decorator\LoggerInterface;
use App\Interface\Test\Proxy\UserInfoInterface; use App\Interface\Test\Proxy\UserInfoInterface;
use App\Lib\Request\GuzzleHttpClient; use App\Lib\Request\GuzzleHttpClient;
use App\Service\Test\Adapter\Cache\RedisCacheService; use App\Service\Test\Adapter\Cache\RedisCacheService;
use App\Service\Test\Bridge\Pay\Lib\AlipayPayment;
use App\Service\Test\Bridge\Pay\Lib\CreditCardPayment;
use App\Service\Test\Bridge\Pay\PremiumPaymentService;
use App\Service\Test\Bridge\Pay\StandardPaymentService;
use App\Service\Test\Decorator\Container\BasicFileLogger; use App\Service\Test\Decorator\Container\BasicFileLogger;
use App\Service\Test\Decorator\Container\CriticalLoggerDecorator; use App\Service\Test\Decorator\Container\CriticalLoggerDecorator;
use App\Service\Test\Decorator\Container\IpLoggerDecorator; use App\Service\Test\Decorator\Container\IpLoggerDecorator;
@@ -47,5 +52,17 @@ return [
$logger = make(BasicFileLogger::class); $logger = make(BasicFileLogger::class);
$cache = make(Cache::class); $cache = make(Cache::class);
return make(CacheUserInfoService::class, ['userInfoService' => $service,'logger' => $logger , 'cache' => $cache]); return make(CacheUserInfoService::class, ['userInfoService' => $service,'logger' => $logger , 'cache' => $cache]);
},
// PaymentInterface::class => AlipayPayment::class,
PaymentInterface::class => CreditCardPayment::class,
'standard_payment' => function () {
$paymentInterface = make(PaymentInterface::class);
$logger = make(BasicFileLogger::class);
return new StandardPaymentService($paymentInterface,$logger);
},
'premium_payment' => function () {
$paymentInterface = make(PaymentInterface::class);
$logger = make(BasicFileLogger::class);
return new PremiumPaymentService($paymentInterface,$logger);
} }
]; ];

36
document/bridge.md Normal file
View File

@@ -0,0 +1,36 @@
### 桥接模式 (Bridge Pattern) 详解
> 桥接模式是一种结构型设计模式,它通过将抽象部分与实现部分分离,使它们可以独立变化而不互相影响。这种模式使用组合关系代替继承关系,从而降低了抽象和实现之间的耦合度。
#### 核心概念
用组合代替继承,将多维度的变化拆分为多个正交的维度,每个维度独立变化。
#### 结构
- 抽象部分(Abstraction): 定义高层的抽象接口/包含一个对实现部分的引用
- 精确抽象(Refined Abstraction): 扩展抽象部分的变体
- 实现接口(Implementor): 定义实现类的接口
- 具体实现(Concrete Implementor): 实现Implementor接口的具体类
#### 优缺点
##### 优点
- 分离抽象和实现:可以独立扩展两者
- 提高可扩展性:可以独立添加新的抽象或实现
- 避免继承爆炸:通过组合代替多层继承
- 符合开闭原则:新增维度不影响现有代码
##### 缺点
- 增加系统复杂度:需要正确识别抽象和实现两个维度
- 对高内聚类不适用:如果抽象和实现本身高度耦合,强行分离反而不好
#### 桥接模式 vs 其他模式
| 模式 | 区别 |
|--------|-----------------------|
| 适配器模式 | 适配器是事后补救,桥接是事先设计 |
| 抽象工厂模式 | 抽象工厂关注产品族,桥接关注分离抽象与实现 |
| 策略模式 | 策略模式改变行为,桥接模式分离抽象与实现 |
桥接模式通过这种分离设计,让系统获得更好的扩展性和维护性,是多维度变化场景下的优秀解决方案。

View File

@@ -50,4 +50,9 @@ Content-Type: application/x-www-form-urlencoded
### Proxy get_user_info test ### Proxy get_user_info test
GET {{host}}/proxy/test/get_user_info?user_id=2 GET {{host}}/proxy/test/get_user_info?user_id=2
Content-Type: application/x-www-form-urlencoded
### Bridge pay test
GET {{host}}/bridge/test/pay
Content-Type: application/x-www-form-urlencoded Content-Type: application/x-www-form-urlencoded