>  기사  >  PHP 프레임워크  >  Laravel 인터페이스 지향 프로그래밍(연습)

Laravel 인터페이스 지향 프로그래밍(연습)

Guanhui
Guanhui앞으로
2020-05-21 11:06:213467검색

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);
        }
    }
}

훨씬 좋습니다. 이제 추가 로깅 대상을 추가하려면 새 클래스를 생성하고 이를 컨트롤러의 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은 기본적으로 메소드 주입을 제공하므로 인터페이스와 구현만 바인딩하면 됩니다.

먼저 로거 구성 파일을 생성해야 합니다. 이렇게

<?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 인터페이스를 사용할 때 컨테이너는 기본 Logger 인스턴스를 구문 분석하고 반환합니다.

env() 어시스턴트를 사용하여 기본 로거를 지정하기 때문에 로컬 환경의 파일, 프로덕션 환경의 db 등 다양한 환경에서 서로 다른 로거를 사용할 수 있습니다.

요약

인터페이스를 사용하면 낮은 결합 코드를 작성하고 추상화 계층을 제공할 수 있습니다. 이를 통해 언제든지 구현을 변경할 수 있습니다. 따라서 가능한 한 인터페이스 지향 방식으로 애플리케이션의 변수 부분을 구현하도록 노력하십시오.

추천 튜토리얼: "PHP 튜토리얼"

위 내용은 Laravel 인터페이스 지향 프로그래밍(연습)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 learnku.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제