首页 php框架 Laravel Laravel 面向接口编程(实践)

Laravel 面向接口编程(实践)

May 21, 2020 am 11:06 AM
laravel php

Laravel 面向接口编程(实践)

面向接口编程是编码中的一种设计思想,这种方式基于接口而不是固定的类来构建应用程序。

如果您是一名程序员,那么您可能听说过则这样的说法,例如:面向接口编程、使用抽象类代替固定类等等。

这些都是说的同一件事,编写应用程序代码时,使其依赖抽象接口而不是具体的类。

为什么?

这是我第一次听到这句话时的确切反应。为什么要使用接口而不是类?即使创建了接口,我也需要创建一个实现该接口的类。这不是浪费时间吗?

当然不是!!

这个世界上唯一不变的就是变化本身,也就是说,变化是永恒的。

就编程而言,这同样没有例外。业务需求随着时间变化,我们的代码也要随之变化。

所以代码必需保持灵活。

面向接口编程可以使代码松散耦合且灵活。

怎么做?

观察下面的代码。

class Logger {
    public function log($content) 
    {
        //日志保存到文件中.
        echo "Log to file";
    }
}
登录后复制

这是一个将日志记录到文件的简单类。 我们可以在控制器中调用它。

class LogController extends Controller
{
    public function log()
    {
        $logger = new Logger;
        $logger->log('Log this');
    }
}
登录后复制

但如果需要将日志记录到多个地方 (如数据库,文件,云端等) 时,我们又该怎么办呢。

然后我们可以更改 LogController 和 Logger 类以适应这些更改。

class Logger {
    public function logToDb($content) 
    {
        //将日志记录到 db.
    }
    public function logToFile($content) 
    {
        //将日志保存到 file.
    }
    public function logToCloud($content) 
    {
        //将日志存储到 cloud.
    }
}
登录后复制
class LogController extends Controller
{
    public function log()
    {
        $logger = new Logger;
        $target = config('log.target');
        if ($target == 'db') {
            $logger->logToDb($content);
        } elseif ($target == 'file') {
            $logger->logToFile($content);
        } else {
            $logger->logToCloud($content);
        }
    }
}
登录后复制

现在我们可以记录不同的目标了。但是,如果我们想将其他目标 (例如日志) 添加到 redis 服务器,该怎么办?最后,我们将同时修改 Logger 类和 LogController 类。

如您所见,这很快就摆脱了我们的控制,并且代码变得混乱。Logger 类很快成为一个整体。这是一场噩梦。

因此,我们需要拆分事物。遵循 SOLID 原则,我们可以将职责移至相应的类。

class DBLogger
{
    public function log()
    {
        //将日志记录到 db
    }
}
class FileLogger
{
    public function log()
    {
        //将日志保存到 file
    }
}
class CloudLogger
{
    public function log()
    {
        //将日志存储到 cloud
    }
}
登录后复制

并且控制器更改为:

class LogController extends Controller
{
    public function log()
    {
        $target = config('log.target');
        if ($target == 'db') {
            (new DBLogger)->log($content);
        } elseif ($target == 'file') {
            (new FileLogger)->log($content);
        } else {
            (new CloudLogger)->log($content);
        }
    }
}
登录后复制

这样就好多了。现在如果要添加其他日志记录目标,我们可以创建一个新类并将其添加到 Controller 中的 if-else。

但是,我们的控制器仍然负责选择记录器。对于控制器,不需要知道不同的记录器并在它们之间进行选择。它只需要一个带有 log() 方法的记录器类来记录内容。

使用接口

这种情况就适合使用接口。那么什么是接口?

接口是对对象可以执行的操作的描述。

以我们的示例为例,控制器仅需要带有 log() 方法的记录器类。因此,我们的接口必须描述它必须具有 log() 方法。

interface Logger
{
    public function log($content);
}
登录后复制

如您所见,它仅包含函数声明,而不包含其实现,这就是为什么将其称为抽象的原因。

实现接口时,实现接口的类必须提供接口中定义的抽象方法的实现细节。

在我们的示例中,任何实现 Logger 接口的类都必须提供抽象方法 log () 的实现细节。

然后,我们可以在控制器中注入此接口。

class LogController extends Controller
{
    public function log(Logger $logger)
    {
        $logger->log($content);
    }
}
登录后复制

现在,控制器不再关心传递给它的记录器类型。它需要知道的是它必须实现 Logger 接口。

因此,我们需要修改 Logger 类以实现此接口。

class DBLogger implements Logger
{
    public function log()
    {
        //将日志记录到 db
    }
}
class FileLogger implements Logger
{
    public function log()
    {
        //将日志存储到 file
    }
}
class CloudLogger implements Logger
{
    public function log()
    {
        //将日志保存到 cloud
    }
}
登录后复制

现在,我们可以添加更多记录器,而无需触及现有代码。我们要做的就是创建一个实现 Logger 接口的新类。

class RedisLogger implements Logger
{
    public function log()
    {
        //将日志存储到 redis
    }
}
登录后复制

我们的代码现在看起来就变得灵活,低耦合了,我们可以随时改变实现方式而不用去改动之前的代码。

依赖注入

当我们使用的是 Laravel 框架,我们可以使用服务容器去自动注册接口的实现。

因为 Laravel 提供开箱即用的方法注入,所以我们只需要把接口和实现绑定起来。

首先我们需要创建一个 logger 的配置文件。 就像这样

<?php
return [
    &#39;default&#39; => env(&#39;LOG_TARGET&#39;, &#39;file&#39;),
    &#39;file&#39; => [
        &#39;class&#39; => App\Log\FileLogger::class,
    ],
    &#39;db&#39; => [
        &#39;class&#39; => App\Log\DBLogger::class,
    ],
    &#39;redis&#39; => [
        &#39;class&#39; => App\Log\RedisLogger::class,
    ]
];
登录后复制

然后在 app/Providers 路径下 AppServiceProvider.php 的文件添加如下代码

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $default = config(&#39;log.default&#39;);
        $logger = config("log.{$default}.class");
        $this->app->bind(
            App\Contracts\Logger::class, // the logger interface
            $logger
        );
    }
}
登录后复制

这样做的效果是,从 logger.php 配置文件读取默认的 logger ,然后绑定到 Logger interface 。这样当我们使用 Logger interface ,容器将会帮我们解析并返回默认的 Logger 实例。

因为默认的 logger 是使用 env() 助手指定的,所以我们可以在不同的环境使用不同的 logger ,例如本地环境使用 file ,生产环境使用 db 。

总结

使用接口可以让我们写出低耦合的代码,提供一个抽象层。它允许我们随时改变实现方式。所以,尽可能将你的应用中可变的部分用面向接口的方式实现。

推荐教程:《PHP教程

以上是Laravel 面向接口编程(实践)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
<🎜>掩盖:探险33-如何获得完美的色度催化剂
2 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1677
14
CakePHP 教程
1430
52
Laravel 教程
1333
25
PHP教程
1278
29
C# 教程
1257
24
session_start()函数的意义是什么? session_start()函数的意义是什么? May 03, 2025 am 12:18 AM

session_start()iscucialinphpformanagingusersessions.1)ItInitiateSanewsessionifnoneexists,2)resumesanexistingsessions,and3)setsasesessionCookieforContinuityActinuityAccontinuityAcconActInityAcconActInityAcconAccRequests,EnablingApplicationsApplicationsLikeUseAppericationLikeUseAthenticationalticationaltication and PersersonalizedContentent。

php框架laravel和yii区别是什么 php框架laravel和yii区别是什么 Apr 30, 2025 pm 02:24 PM

Laravel和Yii的主要区别在于设计理念、功能特性和使用场景。1.Laravel注重开发的简洁和愉悦,提供丰富的功能如EloquentORM和Artisan工具,适合快速开发和初学者。2.Yii强调性能和效率,适用于高负载应用,提供高效的ActiveRecord和缓存系统,但学习曲线较陡。

如何使用MySQL的函数进行数据处理和计算 如何使用MySQL的函数进行数据处理和计算 Apr 29, 2025 pm 04:21 PM

MySQL函数可用于数据处理和计算。1.基本用法包括字符串处理、日期计算和数学运算。2.高级用法涉及结合多个函数实现复杂操作。3.性能优化需避免在WHERE子句中使用函数,并使用GROUPBY和临时表。

Laravel 最佳扩展包推荐:2024 年必备工具 Laravel 最佳扩展包推荐:2024 年必备工具 Apr 30, 2025 pm 02:18 PM

2024年必备的Laravel扩展包包括:1.LaravelDebugbar,用于监控和调试代码;2.LaravelTelescope,提供详细的应用监控;3.LaravelHorizon,管理Redis队列任务。这些扩展包能提升开发效率和应用性能。

作曲家:PHP开发人员的软件包经理 作曲家:PHP开发人员的软件包经理 May 02, 2025 am 12:23 AM

Composer是PHP的依赖管理工具,通过composer.json文件管理项目依赖。1)解析composer.json获取依赖信息;2)解析依赖关系形成依赖树;3)从Packagist下载并安装依赖到vendor目录;4)生成composer.lock文件锁定依赖版本,确保团队一致性和项目可维护性。

Laravel 日志与错误监控:Sentry 和 Bugsnag 集成 Laravel 日志与错误监控:Sentry 和 Bugsnag 集成 Apr 30, 2025 pm 02:39 PM

在Laravel中集成Sentry和Bugsnag可以提高应用的稳定性和性能。1.在composer.json中添加SentrySDK。2.在config/app.php中添加Sentry服务提供者。3.在.env文件中配置SentryDSN。4.在App\Exceptions\Handler.php中添加Sentry错误报告。5.使用Sentry捕获并报告异常,并添加额外上下文信息。6.在App\Exceptions\Handler.php中添加Bugsnag错误报告。7.使用Bugsnag监

Laravel 实时聊天应用:WebSocket 与 Pusher 结合 Laravel 实时聊天应用:WebSocket 与 Pusher 结合 Apr 30, 2025 pm 02:33 PM

在Laravel中构建实时聊天应用需要使用WebSocket和Pusher。具体步骤包括:1)在.env文件中配置Pusher信息;2)设置broadcasting.php文件中的广播驱动为Pusher;3)使用LaravelEcho订阅Pusher频道并监听事件;4)通过PusherAPI发送消息;5)实现私有频道和用户认证;6)进行性能优化和调试。

Laravel N 1 查询问题:如何用 Eager Loading 解决? Laravel N 1 查询问题:如何用 Eager Loading 解决? Apr 30, 2025 pm 01:57 PM

EagerLoading可以解决Laravel中的N 1查询问题。 1)使用with方法预加载相关模型数据,如User::with('posts')->get()。 2)对于嵌套关系,使用with('posts.comments')。 3)避免过度使用,选择性加载,并按需使用load方法。通过这些方法,可以显着减少查询次数,提升应用性能。

See all articles