laravel 依赖注入 接口设计
假设我现在需要做一个支付服务,那么我先设计一个接口
interface PayInterface{
public function pay(Order $order) : string;
}
然后实现这个接口
class WeiXinPay implements PayInterface{
public function pay(Order $order) :string{
//具体实现
}
}
开始发现一个问题
微信支付是需要三个关键参数的 (appID , appSecret , key)
我就接着修改代码,我希望这三个参数是通过外部注入的,而不是写死在WeiXinPay里面,于是乎我就修改了WeiXinPay的构造函数,并新增了一个接口与实现
interface PaySettingsInterface {
public function getSettings() : array;
}
class WeixinPaySettings implements PaySettingsInterface{
public function getSettings() : array{
return [
'app_id' => 'xxxx',
'app_secret' => 'yyyyy',
'key' => 'zzzz'
];
}
}
class WeiXinPay implements PayInterface{
protected $settings;
public __construct(PaySettingsInterface $settings){
$this->settings = $settings->getSettings();
}
public function pay(Order $order) :string{
//具体实现
}
}
好了。感觉到这里这个PayInterface的实现应该是没问题了。我开始写服务提供者
$this->app->bind(PaySettingsInterface::class,WeiXinPaySettings::class);
$this->app->bind(PayInterface::class , WeiXinPay::class);
写一段测试代码来跑跑看
public function testPay(){
$orderSn = Strings::randomString('NUMBER+',12);
$order = factory(Order::class)->make([
'sn' => $orderSn,
'uid' => 111,
'to_uid' => 109,
'relation_user' => json_encode([109,108,107,104,102,12]),
'amount' => 1,
'attach' => 1,
'status' => Constans::ORDER_NO_PAY,
'is_settle' => Constans::NO_SETTLE,
]);
/**
* @var $service PayInterface
*/
$service = $this->app->make(PayInterface::class);
$res = $service->pay($order);
$this->assertIsString($res);
}
没有问题,一切都如预期一样。(未来我也可以很容置的将微信支付换成支付宝,只需要在服务提供者切换实现即可)
过了两天,又有一个新的需求了。终极问题来了,老板希望每一次支付的时候收款人都不一样,也就是说微信支付的appId,appSecret,appKey每次都不一样
我开始修改我的代码,我想着:我让这些有变动的参数通过构造函数的方式传递进来总可以吧。
interface PaySettingsInterface {
public function getSettings() : array;
}
class WeixinPaySettings implements PaySettingsInterface{
protected $appID;
protected $appKey;
protected $appSecret;
public function __construct($appID ,$appKey ,$appSecret){
$this->appID = $appID;
$this->appKey = $appKey;
$this->appSecret = $appSecret;
}
public function getSettings() : array{
return [
'app_id' => $this->appID,
'app_secret' => $this->appSecret,
'key' => $this->appKey
];
}
}
class WeiXinPay implements PayInterface{
protected $settings;
public __construct(PaySettingsInterface $settings){
$this->settings = $settings->getSettings();
}
public function pay(Order $order) :string{
//具体实现
}
}
//然后我修改我的服务提供者
$this->app->bind(PaySettingsInterface::class,function($app){
//怎么new 呢? 老板的需求是可能每次都不同,这些数据又可能来自数据库,也可能来自缓存。
$instance = new WeixinPaySettings(???);
return $instance;
});
$this->app->bind(PayInterface::class , WeiXinPay::class);
//到这里,看来是无法通过容器自动注入PaySettingsInterface的实现了。那么我就只能这样了。在测试代码中:
public function testPay(){
$orderSn = Strings::randomString('NUMBER+',12);
$order = factory(Order::class)->make([
'sn' => $orderSn,
'uid' => 111,
'to_uid' => 109,
'relation_user' => json_encode([109,108,107,104,102,12]),
'amount' => 1,
'attach' => 1,
'status' => Constans::ORDER_NO_PAY,
'is_settle' => Constans::NO_SETTLE,
]);
//查询数据库得到settings
$settings = Db::get();
$paySettings = new WeixinPaySettings($settings['app_id'],$settings['app_secret'],$settings['app_key']);
$payService = new WeixinPay($paySettings);
$res = $payService->pay($order);
$this->assertIsString($res);
}
这样看起来也可以,但是我困扰了
- 我没有办法简单的替换支付方式了 (WeixinPay 替换成 AliPay)
- 调用方手动的去new 相关的实现,产生了严重的依赖。
我希望能够:
- 能够简单的替换支付方式(服务提供者)
- 调用方只需要 调用 pay(Order $order) 方法即可完成支付,即使我切换支付对于调用方来说都是不需要改变的,符合里氏替换规则
laravel 依赖注入 接口设计的更多相关文章
- laravel依赖注入 容器
[看完就懂]Laravel 服务容器,IoC,DI DI DI就是常说的依赖注入,那么究竟什么是依赖注入呢? 打个比方,电脑(非笔记本哈)需要键盘和鼠标我们才能进行操作,这个‘需要’换句话说 ...
- ASP.NET Core 6框架揭秘实例演示[06]:依赖注入框架设计细节
由于依赖注入具有举足轻重的作用,所以<ASP.NET Core 6框架揭秘>的绝大部分章节都会涉及这一主题.本书第3章对.NET原生的依赖注入框架的设计和实现进行了系统的介绍,其中设计一些 ...
- Laravel 依赖注入原理
众所周知 Laravel 的文档对于依赖注入只写了如何使用,相信大多数人对于他的实现原理并不太清楚.虽然使用过程中并不需要关心她的原理,但是了解原理让你使用起来更自信.这个帖子就通过一个小 demo ...
- php+laravel依赖注入浅析
laravel容器包含控制反转和依赖注入,使用起来就是,先把对象bind好,需要时可以直接使用make来取就好. 通常我们的调用如下. $config = $container->make('c ...
- laravel依赖注入浅析
laravel容器包含控制反转和依赖注入,使用起来就是,先把对象bind好,需要时可以直接使用make来取就好. 通常我们的调用如下. $config = $container->make('c ...
- laravel 依赖注入
<?php interface Animal{ public function attack(); public function talk(); } class People implemen ...
- 5. Effective Java 第三版——使用依赖注入取代硬连接资源
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——5. 使用依赖注入取代硬连接资源
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- DotNetCore依赖注入实现批量注入
文章转载自平娃子(QQ:273206491):http://os.pingwazi.cn/resource/batchinjectservice 一.依赖注入 通过依赖注入,可以实现接口与实现类的松耦 ...
随机推荐
- Java工程编码格式由GBK转化成utf-8(编码格式互转)
在写项目的过程中我发现有的地方编码格式被设置成了 gbk 如果用eclipse等工具直接改回utf-8编码格式则会出现乱码. 下载:https://download.csdn.net/download ...
- Vue.js高效前端开发知识 • 【目录】
持续更新中- 章节 内容 实践练习 Vue.js高效前端开发 • (实践练习) 第1章 Vue.js高效前端开发 • [ 一.初识Vue.js ] 第2章 Vue.js高效前端开发 • [ 二.Vue ...
- Log4j2完整XML参考(详细注释说明)
1.说明 本文提供完整的log4j2.xml配置文件, 供开发中参考使用,可以作为模板, 配置对应实现如下常用的功能: 1.自动检测和重新加载配置,每10分钟(600s)检测一次 2.每个日志文件最大 ...
- .net core的配置介绍(二):自定义配置(Zookeeper,数据库,Redis)
上一篇介绍了.net core的配置原理已经系统提供的一些常用的配置,但有时我们的配置是存放在Zookeeper,DB,Redis中的,这就需要我们自己去实现集成了. 这里再介绍几个我们用的多的配置集 ...
- netty系列之:netty对SOCKS协议的支持
目录 简介 SocksMessage Socks4Message Socks5Message 总结 简介 SOCKS是一个优秀的网络协议,主要被用来做代理,它的两个主要版本是SOCKS4和SOCKS5 ...
- Pytest_配置文件-pytest.ini(4)
pytest配置文件可以改变pytest的默认运行方式,它是一个固定的文件名称pytest.ini. 存放路径为项目的根目录 解决中文报错 在讲解配置文件的可用参数前,我们先解决一个高概率会遇到的问题 ...
- navicat 找不到系统路径 【修改了系统路径中文名称引起的】
这是我还没修改系统路径中文名称时的路径, 怎么办? 关闭当前用户连接 右键,选择连接属性 把那个改了即可
- 第10组 Alpha冲刺 (4/6)
1.1基本情况 ·队名:今晚不睡觉 ·组长博客:https://www.cnblogs.com/cpandbb/p/13982696.html ·作业博客:https://edu.cnblogs.co ...
- mysql-5.7.20-winx64安装图解教程
原文链接:https://www.toutiao.com/i6494052843912167949/ 将安装包解压 解压目录 鼠标右键"我的电脑",弹出"快捷菜单&quo ...
- Sentry 开发者贡献指南 - Feature Flag
功能 flag 在 Sentry 的代码库中声明. 对于自托管用户,这些标志然后通过 sentry.conf.py 进行配置. 对于 Sentry 的 SaaS 部署,Flagr 用于在生产中配置标志 ...