把 Laravel 服务容器想象成一个大型的汽车维修中心。这个维修中心就像是服务容器,而汽车的各种零部件(如发动机、轮胎、刹车系统等)就好比是应用程序里的各类对象(类的实例)。
当一位技师要维修一辆汽车时,他不需要自己去市场上购买各种零部件来组装,只需要向维修中心的仓库管理员说明需要哪些零部件,管理员就会从仓库里把相应的零部件拿给他。在 Laravel 应用中,当一个类需要依赖其他类的实例时,不用在类内部手动创建这些依赖,只需要向服务容器请求,服务容器就会把相应的实例提供给它,这就是依赖注入。
维修中心里可能有一些特殊的工具,比如高精度的测量仪器,整个维修中心只有一台。无论哪个技师需要使用这个仪器,都会从同一个地方拿到它。在 Laravel 服务容器中,单例模式就类似这种情况,对于某些类,服务容器只创建一个实例,并且在整个应用程序的生命周期内都使用这同一个实例。
想象维修中心里有多种品牌的轮胎可供选择,比如米其林、普利司通等。技师在维修汽车时,只需要告诉管理员需要轮胎,管理员可以根据不同的情况选择不同品牌的轮胎提供给技师。在 Laravel 中,接口就像是 “轮胎” 这个概念,具体的实现类就像不同品牌的轮胎,你可以将接口绑定到不同的具体实现类上,服务容器会根据绑定关系提供合适的实例。
// 定义一个轮胎接口
interface Tire
{
public function getBrand();
}
// 定义米其林轮胎实现类
class MichelinTire implements Tire
{
public function getBrand()
{
return 'Michelin';
}
}
// 定义普利司通轮胎实现类
class BridgestoneTire implements Tire
{
public function getBrand()
{
return 'Bridgestone';
}
}
// 定义汽车类,依赖轮胎接口
class Car
{
private $tire;
public function __construct(Tire $tire)
{
$this->tire = $tire;
}
public function showTireBrand()
{
return 'This car uses ' . $this->tire->getBrand() . ' tires.';
}
}
// 定义特殊工具类,使用单例模式
class SpecialTool
{
private static $instance;
private function __construct() {}
public static function getInstance()
{
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
public function useTool()
{
return 'Using the special tool.';
}
}
// 在 AppServiceProvider 中进行绑定
namespace App\Providers;
use App\Car;
use App\MichelinTire;
use App\BridgestoneTire;
use App\SpecialTool;
use App\Tire;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
// 绑定接口到具体实现
$this->app->bind(Tire::class, function ($app) {
// 这里可以根据不同条件选择不同的实现类,例如配置文件中的设置
return new MichelinTire();
});
// 注册单例
$this->app->singleton(SpecialTool::class, function ($app) {
return SpecialTool::getInstance();
});
// 绑定汽车类
$this->app->bind(Car::class, function ($app) {
return new Car($app->make(Tire::class));
});
}
}
// 在控制器中使用服务容器
namespace App\Http\Controllers;
use App\Car;
use App\SpecialTool;
use Illuminate\Http\Request;
class CarController extends Controller
{
public function showCarInfo()
{
// 获取汽车实例,服务容器自动注入轮胎实例
$car = app(Car::class);
$carInfo = $car->showTireBrand();
// 获取特殊工具单例实例
$tool = app(SpecialTool::class);
$toolUsage = $tool->useTool();
return response()->json([
'car_info' => $carInfo,
'tool_usage' => $toolUsage
]);
}
}
- 接口和实现类:定义了
Tire
接口以及 MichelinTire
和 BridgestoneTire
两个实现类,模拟不同品牌的轮胎。Car
类依赖于 Tire
接口,通过构造函数注入轮胎实例。SpecialTool
类使用单例模式,确保整个应用中只有一个实例。
- 服务提供者:在
AppServiceProvider
中,使用 bind
方法将 Tire
接口绑定到 MichelinTire
实现类,使用 singleton
方法注册 SpecialTool
类为单例,同时绑定 Car
类并注入 Tire
实例。
- 控制器:在
CarController
中,使用 app()
辅助函数从服务容器中获取 Car
实例和 SpecialTool
单例实例,并调用相应的方法输出信息。