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 一.依赖注入 通过依赖注入,可以实现接口与实现类的松耦 ...
随机推荐
- JS运行三部曲(预编译)
JS运行的三个步骤: 语法分析 预编译 解释执行 语法分析:通俗来说就是通篇检查你的代码有没有语法错误,有语法错误的话,程序是不会执行的 解释执行:也就是程序读一句执行一句 最重点的也就是预编译了,那 ...
- SpringCloud创建Eureka模块
1.说明 本文详细介绍Spring Cloud创建Eureka模块的方法, 基于已经创建好的Spring Cloud父工程, 请参考SpringCloud创建项目父工程, 在里面创建Eureka模块, ...
- frontend-maven-plugin插件问题解决
1.插件介绍 frontend-maven-plugin为项目本地下载/安装Node和NPM,运行npm install命令 . 它适用于Windows,OS X和Linux. 这个插件也可以下载No ...
- Python升级至2.7方法
在Linux下Python升级至2.7的详细步骤方法, 此处的升级,使用的是全新安装新版本,替换旧版本的方法, 同时新旧版本可以共存,将默认python指向最新2.7版本即可. 1.下载Python- ...
- Snack3 3.2 发布,轻量的Json+Jsonpath框架
Snack3 是一个轻量的 JSON + Jsonpath 框架. 借鉴了 Javascript 所有变量由 var 申明,及 Xml dom 一切都是 Node 的设计.其下一切数据都以ONode表 ...
- 初识python 之 ImportError: No module named _ssl
场景 安装好python之后,导入ssl模块报错: ImportError: No module named _ssl 解决方法 查看openssl.openssl-devel是否安装 rpm -qa ...
- MongoDB学习 - 简单使用
1.项目引入pom依赖 <!-- mongodb --><dependency> <groupId>org.springframework.boot</gro ...
- Ant <Delete> 如何只删掉文件夹下所有文件和文件夹
用 fileset 来过滤要删掉的目录和文件 <project name="ant-project" default="example"> < ...
- CentOS6.9部署Redis3.2.9+FastDFS_4.06+Nginx1.5.0
CentOS6.9部署Redis3.2.9+FastDFS_4.06+Nginx1.5.0 原文链接:https://www.toutiao.com/i6481931577499582990/ 一.上 ...
- [解决] No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
前端时间项目组让我改一个比较老的项目,说是用Android Studio2.3版本可以直接运行,于是我下载了一个2.3.2的,结果出现了一堆问题,总结下: 首先导入项目后build完直接报出:No t ...