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 一.依赖注入 通过依赖注入,可以实现接口与实现类的松耦 ...
随机推荐
- 云南农职《JavaScript交互式网页设计》 综合机试试卷①——实现购物车的结算
一.语言和环境 实现语言:javascript.html.css. 开发环境:HBuilder. 二.题目2(100分) 1.功能需求: 马上过节了,电商网站要进行促销活动,需要实现该商城购物车的商品 ...
- Jenkins_构建任务提示找不到命令的处理方法
问题现象 部署pytest环境后,在linux上能执行命令,但是使用jenkins构建就提示找不到命令. 问题分析 可能是...jenkins中执行时,默认使用的是linux中的jenkins用户权限 ...
- spring security 登出操作 详细说明
1.前言 这里专门 做 spring security 登出操作 的 详细记录 2.操作 (1)目录结构 (2)在security 拦截规则配置文件添加退出登录支持 源码 package com.e ...
- 读取 properties 配置文件含有中文的value内容 导致中文乱码 的解决办法
1.前言 因为装系统的时候把中文写在了系统路径,现在我想把这个路径写在properties里面来读取,可是 发现java 读取会导致中文乱码成 问号????的乱码 ,百度找了好多博客,基本都是一摸一 ...
- 上传自己的pip模块
对于模块开发者本质上需要做3件事: 编写模块 将模块进行打包 上传到PyPI(需要先注册PyPI账号) 注册PyPI账号 安装上传工具 基于工具进行上传 对于模块的使用者来说,只需要做2件事: 通过p ...
- Go语言系列之知识框架
一.Go基础入门知识 二.变量和基本数据类型 三.流程控制语句 四.数组和切片 五.map的声明和使用 六.函数func方法 七.指针和地址 八.结构体 九.接口interface 十.并发神器gor ...
- HDU 1106 (1.3.5) 排序 (C语言描述)
排序 Problem Description 输入一行数字,如果我们把这行数字中的'5'都看成空格,那么就得到一行用空格分割的若干非负整数(可能有些整数以'0'开头,这些头部的'0'应该被忽略掉,除非 ...
- boot项目打包剔除配置文件(打包优化)
背景: 最近在项目开发中,在本地开发和线上部署的时候总是切换dev和pro环境,项目多了改起来还是很麻烦的,以下记录下boot项目的打包优化,打包的时候剔除配置文件,然后将配置文件手动放到线上,线上项 ...
- 输出前 n 个Fibonacci数
本题要求编写程序,输出菲波那契(Fibonacci)数列的前N项,每行输出5个,题目保证输出结果在长整型范围内.Fibonacci数列就是满足任一项数字是前两项的和(最开始两项均定义为1)的数列,例如 ...
- C#获取http图片
public Image GetHttpImage(string url) { var client = new HttpClient(); var uri = new Uri(Uri.EscapeU ...