programing

인터페이스 주입 및 공통 클래스

codeshow 2023. 4. 2. 11:40
반응형

인터페이스 주입 및 공통 클래스

난 OOP 원칙을 이해하려고 노력중이야. 그리고 내 수업들을 코딩하고 있지.학습 수단으로 워드프레스에서 작성한 몇 가지 기능을 OOP 클래스로 전환하기로 했습니다.이러한 기능은 URL에 설정된 레퍼러(4개)에 따라 1페이지에 올바른 투고 링크를 출력하기 위해 함께 동작합니다.

기본 워크플로우를 사용한 설정은 다음과 같습니다(워크플로우는 진행에 따라 변경될 수 있습니다).

여기에 이미지 설명 입력

아카이브 페이지에 따라 URL에 대해 분류 페이지용 쿼리 변수 1개, 작성자 페이지용 쿼리 변수 1개 등 4개의 쿼리 변수를 설정한다.어떤 페이지도 사용자 지정 쿼리 변수를 두 개 이상 가질 수 없습니다.는 첫 변수와 이 경우 4개의 변수는 4개의 글로벌 변수와 대조됩니다.이 경우$_GET는 반에서, 은 4개의 변수를 하드코드하지 않았습니다. 그리고 이것은$_GET수업을 시험할 수 있도록 하는 것도 좋습니다.에 쌍은 을 됩니다.has* 반환됩니다.null 데이터를 검사되는 미가공 데이터하는 클래스에 의해 데이터)입니다.

풀클래스입니다

<?php
namespace PG\Single\Post\Navigation;

/**
 * Test set values against the super global given. Returns conditional properties
 * which is boolean values. true is returned on success and false on failure.
 *
 * @param $superGlobalVar Super global to test the values against
 * @param (string) $authorReferrer 
 * @param (string) $dateReferrer 
 * @param (string) $searchReferrer 
 * @param (string) $taxReferrer 
*/ 
class RequestReferrerHandler implements RequestReferrerHandlerInterface
{
    /**
     * @since 1.0.0
     * @access protected
     * @var (array) $superGlobalVar
    */
    protected $superGlobalVar;

    /**
     * @since 1.0.0
     * @access protected
     * @var (string) $authorReferrer
    */
    protected $authorReferrer;

    /**
     * @since 1.0.0
     * @access protected
     * @var (string) $dateReferrer
    */
    protected $dateReferrer;

    /**
     * @since 1.0.0
     * @access protected
     * @var (string) $searchReferrer
    */
    protected $searchReferrer;

    /**
     * @since 1.0.0
     * @access protected
     * @var (string) $taxReferrer
    */
    protected $taxReferrer;


    /**
     * Public constructor method.
     *
     * @param $superGlobalVar  Super global to get data from
     * @param $authorReferrer  Query variable from author referrer to test
     * @param $dateReferrer    Query variable from date referrer to test
     * @param $searchReferrer  Query variable from search referrer to test
     * @param $taxReferrer     Query variable from taxonomy referrer to test
    */
    public function __construct($superGlobalVar = null, $authorReferrer= null, $dateReferrer = null, $searchReferrer = null, $taxReferrer = null)
    {
        $this->superGlobalVar = $superGlobalVar;
        $this->authorReferrer = $authorReferrer;
        $this->dateReferrer   = $dateReferrer;
        $this->searchReferrer = $searchReferrer;
        $this->taxReferrer    = $taxReferrer;
    }

    /**
     * Setter setSuperGlobalVar.
     *
     * @since 1.0.0
     * @param $superGlobalVar
     * @return $this
     */
    public function setSuperGlobalVar($superGlobalVar)
    {
        $this->superGlobalVar = $superGlobalVar;
        return $this;
    }   

    /**
     * Returns an array of super global variables.
     *
     * @since 1.0.0
     * @return (array) $this->superGlobalVar
    */ 
    public function getSuperGlobalVar()
    {
        return $this->superGlobalVar;
    }

    /**
     * Setter setAuthorReferrer
     *
     * @since 1.0.0
     * @param $authorReferrer
     * @return $this
     */
    public function setAuthorReferrer($authorReferrer)
    {
        $this->authorReferrer = $authorReferrer;
        return $this;
    }   

    /**
     * Returns the value of the $authorReferrer property.
     *
     * @since 1.0.0
     * @return (array) $this->authorReferrer
    */ 
    public function getAuthorReferrer()
    {
        return $this->authorReferrer;
    }

    /**
     * Setter setDateReferrer.
     *
     * @since 1.0.0
     * @param $dateReferrer
     * @return $this
     */
    public function setDateReferrer($dateReferrer)
    {
        $this->dateReferrer = $dateReferrer;
        return $this;
    }   

    /**
     * Returns the value of the $dateReferrer property.
     *
     * @since 1.0.0
     * @return (array) $this->dateReferrer
    */ 
    public function getDateReferrer()
    {
        return $this->dateReferrer;
    }

    /**
     * Setter setSearchReferrer.
     *
     * @since 1.0.0
     * @param $searchReferrer
     * @return $this
     */
    public function setSearchReferrer($searchReferrer)
    {
        $this->searchReferrer = $searchReferrer;
        return $this;
    }   

    /**
     * Returns the value of the $searchReferrer property.
     *
     * @since 1.0.0
     * @return (array) $this->searchReferrer
    */ 
    public function getSearchReferrer()
    {
        return $this->searchReferrer;
    }

    /**
     * Setter setTaxReferrer.
     *
     * @since 1.0.0
     * @param $taxReferrer
     * @return $this
     */
    public function setTaxReferrer($taxReferrer)
    {
        $this->taxReferrer = $taxReferrer;
        return $this;
    }   

    /**
     * Returns the value of the $taxReferrer property.
     *
     * @since 1.0.0
     * @return (array) $this->taxReferrer
    */ 
    public function getTaxReferrer()
    {
        return $this->$taxReferrer;
    }

    /**
     * Test $authorReferrer against $superGlobalVar.
     *
     * @since 1.0.0
     * @return (bool) true on success or false on failure
     */
    public function isAuthorReferrer()
    {
        if ($this->authorReferrer && isset($this->superGlobalVar[$this->authorReferrer])) { 
            $isAuthorReferrer = true;
        } else {
            $isAuthorReferrer = false;
        }
        return $isAuthorReferrer;
    }

    /**
     * Test $authorReferrer against $superGlobalVar
     *
     * @since 1.0.0
     * @return (bool) true on success or false on failure
     */
    public function isDateReferrer()
    {
        if ($this->dateReferrer && isset($this->superGlobalVar[$this->dateReferrer])) { 
            $isDateReferrer = true;
        } else {
            $isDateReferrer = false;
        }
        return $isDateReferrer;
    }

    /**
     * Test $authorReferrer against $superGlobalVar.
     *
     * @since 1.0.0
     * @return (bool) true on success or false on failure
     */
    public function isSearchReferrer()
    {
        if ($this->searchReferrer && isset($this->superGlobalVar[$this->searchReferrer])) { 
            $isSearchReferrer = true;
        } else {
            $isSearchReferrer = false;
        }
        return $isSearchReferrer;
    }

    /**
     * Test $authorReferrer against $superGlobalVar.
     *
     * @since 1.0.0
     * @return (bool) true on success or false on failure
     */
    public function isTaxReferrer()
    {
        if ($this->taxReferrer && isset($this->superGlobalVar[$this->taxReferrer])) { 
            $isTaxReferrer = true;
        } else {
            $isTaxReferrer = false;
        }
        return $isTaxReferrer;
    }

    /**
     * Conditional which check if the current post is a referred post.
     *
     * @since 1.0.0
     * @return (bool) true on success or false on failure
     */
    public function isReferredPost()
    {
        if ($this->isAuthorReferrer() || $this->isDateReferrer() || $this->isSearchReferrer() || $this->isTaxReferrer()) {
            $isReferredPost = true;
        } else {
            $isReferredPost = false;
        }
        return $isReferredPost;
    }

    /**
     * Return the value from the super global when the current post is a post referred from
     * an author archive page.
     *
     * @since 1.0.0
     * @return (array) $authorReferrerValue
     */ 
    public function hasAuthorReferrerValue()
    {
        if ($this->isAuthorReferrer()) {
            $authorReferrerValue = [$this->authorReferrer => $this->superGlobalVar[$this->authorReferrer]];
        } else {
            $authorReferrerValue = null;
        }
        return $authorReferrerValue;
    }

    /**
     * Return the value from the super global when the current post is a post referred from
     * a date archive page.
     *
     * @since 1.0.0
     * @return (array) $dateReferrerValue
     */ 
    public function hasDateReferrerValue()
    {
        if ($this->isDateReferrer()) {
            $dateReferrerValue = [$this->dateReferrer => $this->superGlobalVar[$this->dateReferrer]];
        } else {
            $dateReferrerValue = null;
        }
        return $dateReferrerValue;
    }

    /**
     * Return the value from the super global when the current post is a post referred from
     * a search page.
     *
     * @since 1.0.0
     * @return (array) $searchReferrerValue
     */ 
    public function hasSearchReferrerValue()
    {
        if ($this->isSearchReferrer()) {
            $searchReferrerValue = [$this->searchReferrer => $this->superGlobalVar[$this->searchReferrer]];
        } else {
            $searchReferrerValue = null;
        }
        return $searchReferrerValue;
    }

    /**
     * Return the value from the super global when the current post is a post referred from
     * a taxonomy archive page.
     *
     * @since 1.0.0
     * @return (array) $taxReferrerValue
     */ 
    public function hasTaxReferrerValue()
    {
        if ($this->isTaxReferrer()) {
            $taxReferrerValue = [$this->taxReferrer => $this->superGlobalVar[$this->taxReferrer]];
        } else {
            $taxReferrerValue = null;
        }
        return $taxReferrerValue;
    }

}

나는 이 수업을 이렇게 사용한다.

$b = new RequestReferrerHandler($_GET, 'aq', 'dq', 'sq', 'tq');
?><pre><?php var_dump($b->hasAuthorReferrerValue()); ?></pre><?php
?><pre><?php var_dump($b->hasDateReferrerValue()); ?></pre><?php
?><pre><?php var_dump($b->hasSearchReferrerValue()); ?></pre><?php
?><pre><?php var_dump($b->hasTaxReferrerValue()); ?></pre><?php

는 이런 하면 됩니다.['aq' => '1'] $_GET

이게 내가 지금 어떻게 해야 할지 막막한 곳이야.를 query arguments로 . 문의하다has*클래스에서 의 클래스에서 「1」이 됩니다.query_vars또한 에서has* 되는 상기

즉, 두 클래스는 위의 클래스의 메서드에 동일한 것을 사용합니다.

hasAuthorReferrerValue();
hasDateReferrerValue();
hasSearchReferrerValue();
hasTaxReferrerValue();

예를 들어, 여기 두 개의 클래스가 어떻게 보여야 하는지에 대한 예가 있습니다.(코드 관리를 용이하게 하기 위해 여기서 몇 가지 방법을 생략했습니다.)

클래스 A

<?php
namespace PG\Single\Post\Navigation;

class ClassA //Just a generic name for testing purposes. Will also implement ClassAInterface
{
    protected $handler;

    public function __construct(RequestReferrerHandlerInterface $handler)
    {
        $this->handler = $handler;
    }

    public function santizeAuthor() 
    {
        $author = $this->handler->hasAuthorReferrerValue(); // Value will be either null or single key/value pair array. Example ['aq' => '1']

        if ($author) {
            $author = array_values($author);
            $author = ['author' => (int)htmlspecialchars($author[0])]; //Will output ['author' => 1]
        }

        return $author; //Returns null or the array ['author' => 1]
    }

    public function santizeDate() 
    {
        $date = $this->handler->hasDateReferrerValue();

        if ($date) {
            // @TODO Still to work out
        }

        return $date;
    }

    //etc

    public function queryArguments() // Will be used in the controller class ClassC
    {
        $queryArgs = null;

        if ($this->santizeAuthor()) {

            $queryArgs = $this->santizeAuthor();

        } elseif ($this->santizeDate) {

            $queryArgs = $this->santizeDate();

        } // etc
        return $queryArgs; //Will return null if all 4 conditions fail or return the value from the one that returns true
    }

}

클래스 B

<?php
namespace PG\Single\Post\Navigation;

class ClassB //Just a generic name for testing purposes. Will also implement ClassBInterface
{
    protected $handler;

    public function __construct(RequestReferrerHandlerInterface $handler)
    {
        $this->handler = $handler;
    }

    public function santizeAuthor() 
    {
        $author = $this->handler->hasAuthorReferrerValue(); // Value will be either null or single key/value pair array. Example ['aq' => '1']

        if ($author) {
            foreach ($author as $k=>$v)
                $author[htmlspecialchars($k)] = (int)htmlspecialchars($v);
        }

        return $author; //Returns null or the array ['aq' => 1]
    }

    public function santizeDate() 
    {
        $date = $this->handler->hasDateReferrerValue();

        if ($date) {
            // @TODO Still to work out
        }

        return $date;
    }

    //etc

    public function queryVars() // Will be used in the controller class ClassC
    {
        $queryVars = null;

        if ($this->santizeAuthor()) {

            $queryVars = $this->santizeAuthor();

        } elseif ($this->santizeDate) {

            $queryVars = $this->santizeDate();

        } // etc
        return $queryVars; //Will return null if all 4 conditions fail or return the value from the one that returns true
    }

}

queryArguments() from method method method method 。ClassAqueryVars() from method method method method 。ClassB다른 클래스(또는1개의 컨트롤러 클래스)에서 사용됩니다.

OOP에 대한 저의 완전한 지식 부족, 관심의 분리, 캡슐화, SOLID 원칙 및 수업의 테스트 가능성의 혼란으로 인해 코드를 다시 추측할 수 있게 되었고, 제가 뭔가를 놓치고 있다고 느꼈습니다.

위 사항을 최적화할 수 있는 방법이 있을까요?코드 재작성을 요구하는 것은 아닙니다.필요한 것은, 이것이 표준이 아닌 경우, 이것을 최적화하기 위한 적절한 포인터와 아이디어 뿐입니다.코드 샘플을 줄 수 있는 사람이 있다면 정말 좋을 거야 윤곽 골격 같은 거 말이야

코드를 확인해보니 확실히 시작이 좋으시네요.OOP에서 프로그래밍할 때 이미 구현이 아닌 인터페이스에 대한 프로그램이라는 하나의 좋은 경험 규칙을 사용하고 있습니다.인터페이스라는 용어는 실제 인터페이스뿐만 아니라 추상 클래스도 의미합니다.

은 두 가지 즉 두 가지 입니다.ClassA ★★★★★★★★★★★★★★★★★」ClassB다을 알 수 있습니다.RequestReferrerHandler하기 위한 기초 되어 있습니다.RequestReferrerHandlerInterface다음과 같은 인터페이스가 있다고 가정합니다.

interface RequestReferrerHandlerInterface
{
    public function hasAuthorReferrerValue();
    public function hasDateReferrerValue();
    public function hasSearchReferrerValue();
    public function hasTaxReferrerValue();
}

가 「」에 있는 한.RequestReferrerHandler의 컨스트럭터 를 입력할 수 있습니다.ClassA ★★★★★★★★★★★★★★★★★」ClassB하지만 이미 하고 있었으니까 새로운 건 아니에요.

특히 엄지손가락 통증으로 눈에 띄는 것이 두 가지 있습니다.에, 의 책임을 , 수업의 책임을 작게 하고 싶기 때문에, 수업의 책임을 시간에 자료를 .RequestReferrerHandler그 자체에서 벗어나서 당신의 것을 줍니다.Controller 「 」, 「 」를 주세요$_GET아, 아, 아, 아, 아, 아, 아, 네.하세요.Controller한 모든 되어 있습니다.RequestReferrerHandler그러면자,자,자,자,여러분.RequestReferrerHandler이치노

class RequestReferrerHandler implements RequestReferrerHandlerInterface
{
    private $author;
    private $date;
    private $search;
    private $tax;

    public function __construct($author = null, $date = null, $search = null, $tax = null)
    {
        $this->setAuthorReferrer($author);
        $this->setDateReferrer($date);
        $this->setSearchReferrer($search);
        $this->setTaxReferrer($tax);
    }

    public function hasAuthorReferrerValue()
    {
        return $this->author !== null ? true : false;
    }

    public function hasDateReferrerValue()
    {
        return $this->date !== null ? true : false;
    }

    public function hasSearchReferrerValue()
    {
        return $this->search !== null ? true : false;
    }

    public function hasTaxReferrerValue()
    {
        return $this->tax !== null ? true : false;
    }

    public function getAuthorReferrer()
    {
        return $this->author;
    }

    public function getDateReferrer()
    {
        return $this->date;
    }

    public function getSearchReferrer()
    {
        return $this->search;
    }

    public function getTaxReferrer()
    {
        return $this->tax;
    }

    public function setAuthorReferrer($author)
    {
        $this->author = $author;
    }

    public function setDateReferrer($date)
    {
        $this->date = $date;
    }

    public function setSearchReferrer($search)
    {
        $this->search = $search;
    }

    public function setTaxReferrer($tax)
    {
        $this->tax = $tax;
    }
}

에 띄는 은 '오빠'입니다.santize() ?ClassA ★★★★★★★★★★★★★★★★★」ClassB ? ? »sanitizeAuthor()두 학급은 다르지만, 나머지는 어떻습니까?이것은 DRY(Don't Repeat Yourself) 원칙이 도움이 되는 경우입니다.여러 클래스가 유사한 방법으로 데이터를 삭제해야 할 수 있으므로 클래스에서 데이터를 추상화하는 것이 좋습니다.

그 방법을 살펴본 후 구체적인 수업으로 돌아갑시다.먼저 데이터를 삭제할 수 있는 개체에 의해 노출되어야 하는 메서드를 지정하는 새 인터페이스를 만듭니다.

interface SanitizerInterface
{
    public function sanitizeAuthor();
    public function sanitizeDate();
    public function sanitizeSearch();
    public function sanitizeTaxonomy();
}

만약 모든 이 있다면, 당신은 그것을 있을 것입니다.ClassX을, 할 수 .그러나 이 예에서는 그렇지 않다고 말할 것입니다. 가정해 sanitizeAuthor()ClassA ★★★★★★★★★★★★★★★★★」ClassB(코드에 기재되어 있습니다) 및 기타 모든 메서드는 완전히 동일하게 구현됩니다.이것은 sanitizer 메서드를 구현하는 추상 클래스를 사용할 수 있는 경우입니다.

abstract class AbstractSanitizer implements SanitizerInterface
{
    protected $handler;

    public function __construct() {}

    public function setHandler(RequestReferrerHandlerInterface $handler)
    {
        $this->handler = $handler;
    }   

    /* For this example we are saying that sanitizeDate(), sanitizeTaxonomy() and
     * sanitizeSearch() will be the same no matter what.  So let's implement them 
     * and leave the child classes to implement sanitizeAuthor(). 
     * 
     * Implement the details of the sanitizer function to fit your needs.
     */

    public function sanitizeDate()
    {
        if($this->handler !== null)
        {
            //Perform whatever tasks to sanitize the date
            $sanitized = strtoupper($this->handler->getDateReferrer());
            echo "Sanitize date -> switch to uppercase letters.\n";
            $this->handler->setDateReferrer($sanitized);
        }
    }

    public function sanitizeSearch()
    {
        if($this->handler !== null)
        {
            //Perform whatever tasks to sanitize the search
            $sanitized = strtolower($this->handler->getSearchReferrer());
            echo "Sanitize search -> switch to lowercase letters.\n";
            $this->handler->setSearchReferrer($sanitized);
        }
    }

    public function sanitizeTaxonomy()
    {
        if($this->handler !== null)
        {
            //Perform whatever tasks to sanitize the taxonomy
            $sanitized = str_replace(" ", "_", $this->handler->getTaxReferrer());
            echo "Sanitize Taxonomy -> convert spaces to underscores.\n";
            $this->handler->setTaxReferrer($sanitized);
        }
    }

}

즉석에서 주의할 사항들이 있다.요.setHandler()RequestReferrerHandlerInterface게게 왜? ???츠미야할 수 있도록 .RequestReferrerHandler메서드의 과 함께 .

'', '하다', '하다', ''의 방법을 사용하겠습니다.RequestReferrerHandler에서 되지 않은 RequestReferrerHandlerInterfacegetters나 setters와 같은 메서드가 클래스에 포함되어 있다는 것을 알고 있기 때문에, 그 자체로는 당장 문제가 되지 않습니다.단, 인터페이스를 다른 구체적인 오브젝트로 구현하기로 결정했을 경우 인터페이스에 대한 유형 힌트만으로는 이러한 메서드를 사용할 수 없다는 보장은 없습니다.따라서, 우리는 다음 정보를 업데이트 할 필요가 있다.RequestReferrerHandlerInterface그 가용성을 보증하는 방법을 제공합니다.

interface RequestReferrerHandlerInterface
{
    public function hasAuthorReferrerValue();
    public function hasDateReferrerValue();
    public function hasSearchReferrerValue();
    public function hasTaxReferrerValue();
    public function getAuthorReferrer();
    public function getDateReferrer();
    public function getSearchReferrer();
    public function getTaxReferrer();
    public function setAuthorReferrer($author);
    public function setDateReferrer($date);
    public function setSearchReferrer($search);
    public function setTaxReferrer($tax);
}

,, 우리는 그 세정제를 알고 .ClassA ★★★★★★★★★★★★★★★★★」ClassBsanitizeAuthor()법이릅릅 릅릅릅릅릅 클래스 ★★★★★★★★★★★★★★★」AbstractSanitizer원래대로 만들어졌어요sanitizeAuthor()의 메서드SanitizerInteface에 실장되어 있지 않다.AbstractSanitizer기능을 제공하기 위해 확장해야 합니다.그러기 위해서는, 다음의 2개의 클래스가 필요합니다.

class SanitizerForClassA extends AbstractSanitizer
{
    /* This class must provide an implementation for how ClassA will
     * handle the sanitizeAuthor() method.
     */

    public function sanitizeAuthor()
    {
        if($this->handler !== null)
        {
            //Perform whatever tasks to sanitize the for ClassA
            $sanitized = array("author" => $this->handler->getAuthorReferrer());
            echo "Sanitize author -> ClassA makes author an array.\n";
            $this->handler->setAuthorReferrer($sanitized);
        }   
    }
}

class SanitizerForClassB extends AbstractSanitizer
{
    /* This class must provide an implementation for how ClassB will
     * handle the sanitizeAuthor() method.
     */

    public function sanitizeAuthor()
    {
        if($this->handler !== null)
        {
            //Perform whatever tasks to sanitize the for ClassB
            $sanitized = new stdClass();
            $sanitized->author = $this->handler->getAuthorReferrer();
            echo "Sanitize author -> ClassB makes author an object property. \n";
            $this->handler->setAuthorReferrer($sanitized);
        }   
    }
}

두 는 이이음음음음음음음음음음음음음음 can can can can can can can can can can can can can can can can these these these 와 함께 사용할 수 있습니다.ClassA ★★★★★★★★★★★★★★★★★」ClassBRequestReferrerHandler전달되는 방식입니다.

다음 로 넘어가겠습니다. 요?ClassA ★★★★★★★★★★★★★★★★★」ClassB가 알고 있는 ClassAqueryArguments(),ClassBqueryVars() 모두 "클래스 인스턴스"를 .RequestReferrerHandlerInterface ★★★★★★★★★★★★★★★★★」SanitizerInterface그들의 건설자.한 후 를 통해 하여 '1'에 메서드 합니다.ClassA ★★★★★★★★★★★★★★★★★」ClassB

interface SanitizableHandlerInterface
{       
    public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer);
}

interface QueryVarsInterface extends SanitizableHandlerInterface
{
    public function queryVars();
}

interface QueryArgumentsInterface extends SanitizableHandlerInterface
{
    public function queryArguments();
}

이제 본격적으로 시작했으니, 이러한 내용을 사용할 수 있는 클래스를 살펴보겠습니다.

class ClassA implements QueryArgumentsInterface
{
    private $handler;
    private $sanitizer;

    public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer)
    {
        $this->handler = $handler;
        $this->sanitizer = $sanitizer;
        $this->sanitizer->setHandler($this->handler);
    }

    public function queryArguments() // Will be used in the controller class ClassC
    {
        $queryArgs = null;
        if($this->handler->hasAuthorReferrerValue())
        {
            $this->sanitizer->sanitizeAuthor();
            $queryArgs = $this->handler->getAuthorReferrer();
        }
        if($this->handler->hasDateReferrerValue())
        {
            $this->sanitizer->sanitizeDate();
            $queryArgs = $this->handler->getDateReferrer();
        }
        if($this->handler->hasSearchReferrerValue())
        {
            $this->sanitizer->sanitizeSearch();
            $queryArgs = $this->handler->getSearchReferrer();
        }
        if($this->handler->hasTaxReferrerValue())
        {
            $this->sanitizer->sanitizeTaxonomy();
            $queryArgs = $this->handler->getTaxReferrer();
        }
        return $queryArgs; //Will return null if all 4 conditions fail or return the value from the one that returns true
    }

}

class ClassB implements QueryVarsInterface
{
    private $handler;
    private $sanitizer;

    public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer)
    {
        $this->handler = $handler;
        $this->sanitizer = $sanitizer;
        $this->sanitizer->setHandler($this->handler);       
    }

    public function queryVars() // Will be used in the controller class ClassC
    {
        $queryVars = null;
        if($this->handler->hasAuthorReferrerValue())
        {
            $this->sanitizer->sanitizeAuthor();
            $queryVars = $this->handler->getAuthorReferrer();
        }
        if($this->handler->hasDateReferrerValue())
        {
            $this->sanitizer->sanitizeDate();
            $queryVars = $this->handler->getDateReferrer();
        }
        if($this->handler->hasSearchReferrerValue())
        {
            $this->sanitizer->sanitizeSearch();
            $queryVars = $this->handler->getSearchReferrer();
        }
        if($this->handler->hasTaxReferrerValue())
        {
            $this->sanitizer->sanitizeTaxonomy();
            $queryVars = $this->handler->getTaxReferrer();
        }
        return $queryVars; //Will return null if all 4 conditions fail or return the value from the one that returns true
    }
}

여기 있습니다. 기초 공사가 되어 있습니다.컨스트럭터에서는 지정된 핸들러 및 세니타이저 클래스에 대한 속성이 설정되고 세니타이저가 핸들러에 대한 참조가 제공된다는 것을 알 수 있습니다(세니타이저에는 핸들러에 대한 참조가 있으므로 핸들러 내의 세니타이저 속성이 자동으로 갱신됩니다). 지금은 각 반에서 그런 걱정을 할 필요가 없습니다.

그래서 이제 100만 달러의 문제는 어떻게 이것을 사용하는가 하는 것입니다.하죠?ClassA ★★★★★★★★★★★★★★★★★」ClassB을 사용하다

class Controller
{
    public function __construct() {}

    public function doStuff(QueryArgumentsInterface $argsClass, QueryVarsInterface $varsClass)
    {
        var_dump($argsClass->queryArguments());
        var_dump($varsClass->queryVars());
    }
}

하시는 의 ★★★★★★★★★★★★★queryArguments() ★★★★★★★★★★★★★★★★★」queryVars()반환값에 대해 데이터를 삭제해야 합니다.몇 가지 데이터를 연결하여 결과를 확인합니다(주의: 제가 사용한 sanitize 방법 중 당신이 하고 있는 것은 아무것도 없다는 것을 이미 알게 되었기 때문에, 그것들은 단지 예시일 뿐입니다.)

//TEST DRIVE

//Create a controller that will use the classes
$controller = new Controller();

//Now make use of your new shiny handlers and sanitizers
$controller->doStuff(
    new ClassA(new RequestReferrerHandler("Mark Twain", null, null, null), new SanitizerForClassA()), 
    new ClassB(new RequestReferrerHandler(null, "January 1st, 1999", null, null), new SanitizerForClassB())
);

$controller->doStuff(
    new ClassA(new RequestReferrerHandler(null, null, "OK Google Now!", null), new SanitizerForClassA()), 
    new ClassB(new RequestReferrerHandler(null, null, null, "Super Awesome Taxonomy Tables"), new SanitizerForClassB())
);

$controller->doStuff(
    new ClassA(new RequestReferrerHandler(null, "January 1st, 1999", null, null), new SanitizerForClassA()), 
    new ClassB(new RequestReferrerHandler("Mark Twain", null, null, null), new SanitizerForClassB())
);

$controller->doStuff(
    new ClassA(new RequestReferrerHandler(null, null, null, "Super Awesome Taxonomy Tables"), new SanitizerForClassA()), 
    new ClassB(new RequestReferrerHandler(null, null, "OK Google Now!", null), new SanitizerForClassB())
);

출력은 다음과 같습니다.

Sanitize author -> ClassA makes author an array.
array (size=1)
  'author' => string 'Mark Twain' (length=10)
Sanitize date -> switch to uppercase letters.
string 'JANUARY 1ST, 1999' (length=17)
Sanitize search -> switch to lowercase letters.
string 'ok google now!' (length=14)
Sanitize Taxonomy -> convert spaces to underscores.
string 'Super_Awesome_Taxonomy_Tables' (length=29)
Sanitize date -> switch to uppercase letters.
string 'JANUARY 1ST, 1999' (length=17)
Sanitize author -> ClassB makes author an object property.
object(stdClass)[15]
  public 'author' => string 'Mark Twain' (length=10)
Sanitize Taxonomy -> convert spaces to underscores.
string 'Super_Awesome_Taxonomy_Tables' (length=29)
Sanitize search -> switch to lowercase letters.
string 'ok google now!' (length=14)

그래서 이 모든 것에 얼마를 지불했나요?간단한 답변 - 복잡성화면에 약간의 데이터를 출력하기 위해서는 4개의 인터페이스, 1개의 추상 클래스 및 소수의 구체적인 클래스가 필요했습니다.

뭘 얻었는데요?간단한 답변 - 유연성앞으로는 다음 중 하나를 구현하는 클래스를 추가할 수 있습니다.QueryVarsInterface ★★★★★★★★★★★★★★★★★」QueryArgumentsInterface 수업들을 생각해 보세요.ClassC,ClassD ★★★★★★★★★★★★★★★★★」ClassE, 「」의 경우).SanitizerForClassA ★★★★★★★★★★★★★★★★★」SanitizerForClassB세정제 수업을 계속 써야 하는 것은 지루할 것이다.음, 다행인 것은, 처음부터 인터페이스에 프로그래밍을 하고 있었기 때문에, 그러한 문제는 발생하지 않는다는 것입니다.쉽게 만들 수 있습니다.GenericSanitizer 「」를 하고 있습니다.sanitizeAuthor() 이 클래스와 함께 사용할 수 .Controller::doStuff()전문 세정제 강좌가 필요 없는 경우라면요다양한 구체적인 클래스도 쉽게 구현할 수 있습니다.QueryArgumentInterface ★★★★★★★★★★★★★★★★★」QueryVarsInterface현재 클래스를 변경하지 않고 추가하려는 실험 기능을 테스트합니다.

이것으로 OOP 원리에 대한 통찰력을 얻을 수 있기를 바랍니다.여기 위의 모든 코드의 완전한 복사본이 있습니다.이 파일을 빈 PHP 파일에 슬래핑한 후 실행하여 모든 작업을 확인합니다.행복한 프로그래밍!

    <?php

/*
 * INTERFACES
 */

interface RequestReferrerHandlerInterface
{
    public function hasAuthorReferrerValue();
    public function hasDateReferrerValue();
    public function hasSearchReferrerValue();
    public function hasTaxReferrerValue();
    public function getAuthorReferrer();
    public function getDateReferrer();
    public function getSearchReferrer();
    public function getTaxReferrer();
    public function setAuthorReferrer($author);
    public function setDateReferrer($date);
    public function setSearchReferrer($search);
    public function setTaxReferrer($tax);
}

interface SanitizerInterface
{
    public function sanitizeAuthor();
    public function sanitizeDate();
    public function sanitizeSearch();
    public function sanitizeTaxonomy();
}

interface SanitizableHandlerInterface
{       
    public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer);
}

interface QueryVarsInterface extends SanitizableHandlerInterface
{
    public function queryVars();
}

interface QueryArgumentsInterface extends SanitizableHandlerInterface
{
    public function queryArguments();
}

/*
 * ABSTRACT CLASSES
 */

abstract class AbstractSanitizer implements SanitizerInterface
{
    protected $handler;

    public function __construct() {}

    public function setHandler(RequestReferrerHandlerInterface $handler)
    {
        $this->handler = $handler;
    }   

    /* For this example we are saying that sanitizeDate(), sanitizeTaxonomy() and
     * sanitizeSearch() will be the same no matter what.  So let's implement them 
     * and leave the child classes to implement sanitizeAuthor(). 
     * 
     * Implement the details of the sanitizer function to fit your needs.
     */

    public function sanitizeDate()
    {
        if($this->handler !== null)
        {
            //Perform whatever tasks to sanitize the date
            $sanitized = strtoupper($this->handler->getDateReferrer());
            echo "Sanitize date -> switch to uppercase letters.\n";
            $this->handler->setDateReferrer($sanitized);
        }
    }

    public function sanitizeSearch()
    {
        if($this->handler !== null)
        {
            //Perform whatever tasks to sanitize the search
            $sanitized = strtolower($this->handler->getSearchReferrer());
            echo "Sanitize search -> switch to lowercase letters.\n";
            $this->handler->setSearchReferrer($sanitized);
        }
    }

    public function sanitizeTaxonomy()
    {
        if($this->handler !== null)
        {
            //Perform whatever tasks to sanitize the taxonomy
            $sanitized = str_replace(" ", "_", $this->handler->getTaxReferrer());
            echo "Sanitize Taxonomy -> convert spaces to underscores.\n";
            $this->handler->setTaxReferrer($sanitized);
        }
    }

}

/*
 * CONCRETE CLASSES
 */

class RequestReferrerHandler implements RequestReferrerHandlerInterface
{
    private $author;
    private $date;
    private $search;
    private $tax;

    public function __construct($author = null, $date = null, $search = null, $tax = null)
    {
        $this->setAuthorReferrer($author);
        $this->setDateReferrer($date);
        $this->setSearchReferrer($search);
        $this->setTaxReferrer($tax);
    }

    public function hasAuthorReferrerValue()
    {
        return $this->author !== null ? true : false;
    }

    public function hasDateReferrerValue()
    {
        return $this->date !== null ? true : false;
    }

    public function hasSearchReferrerValue()
    {
        return $this->search !== null ? true : false;
    }

    public function hasTaxReferrerValue()
    {
        return $this->tax !== null ? true : false;
    }

    public function getAuthorReferrer()
    {
        return $this->author;
    }

    public function getDateReferrer()
    {
        return $this->date;
    }

    public function getSearchReferrer()
    {
        return $this->search;
    }

    public function getTaxReferrer()
    {
        return $this->tax;
    }

    public function setAuthorReferrer($author)
    {
        $this->author = $author;
    }

    public function setDateReferrer($date)
    {
        $this->date = $date;
    }

    public function setSearchReferrer($search)
    {
        $this->search = $search;
    }

    public function setTaxReferrer($tax)
    {
        $this->tax = $tax;
    }
}

class SanitizerForClassA extends AbstractSanitizer
{
    /* This class must provide an implementation for how ClassA will
     * handle the sanitizeAuthor() method.
     */

    public function sanitizeAuthor()
    {
        if($this->handler !== null)
        {
            //Perform whatever tasks to sanitize the for ClassA
            $sanitized = array("author" => $this->handler->getAuthorReferrer());
            echo "Sanitize author -> ClassA makes author an array.\n";
            $this->handler->setAuthorReferrer($sanitized);
        }   
    }
}

class SanitizerForClassB extends AbstractSanitizer
{
    /* This class must provide an implementation for how ClassB will
     * handle the sanitizeAuthor() method.
     */

    public function sanitizeAuthor()
    {
        if($this->handler !== null)
        {
            //Perform whatever tasks to sanitize the for ClassB
            $sanitized = new stdClass();
            $sanitized->author = $this->handler->getAuthorReferrer();
            echo "Sanitize author -> ClassB makes author an object property. \n";
            $this->handler->setAuthorReferrer($sanitized);
        }   
    }
}

class ClassA implements QueryArgumentsInterface
{
    private $handler;
    private $sanitizer;

    public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer)
    {
        $this->handler = $handler;
        $this->sanitizer = $sanitizer;
        $this->sanitizer->setHandler($this->handler);
    }

    public function queryArguments() // Will be used in the controller class ClassC
    {
        $queryArgs = null;
        if($this->handler->hasAuthorReferrerValue())
        {
            $this->sanitizer->sanitizeAuthor();
            $queryArgs = $this->handler->getAuthorReferrer();
        }
        if($this->handler->hasDateReferrerValue())
        {
            $this->sanitizer->sanitizeDate();
            $queryArgs = $this->handler->getDateReferrer();
        }
        if($this->handler->hasSearchReferrerValue())
        {
            $this->sanitizer->sanitizeSearch();
            $queryArgs = $this->handler->getSearchReferrer();
        }
        if($this->handler->hasTaxReferrerValue())
        {
            $this->sanitizer->sanitizeTaxonomy();
            $queryArgs = $this->handler->getTaxReferrer();
        }
        return $queryArgs; //Will return null if all 4 conditions fail or return the value from the one that returns true
    }

}

class ClassB implements QueryVarsInterface
{
    private $handler;
    private $sanitizer;

    public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer)
    {
        $this->handler = $handler;
        $this->sanitizer = $sanitizer;
        $this->sanitizer->setHandler($this->handler);       
    }

    public function queryVars() // Will be used in the controller class ClassC
    {
        $queryVars = null;
        if($this->handler->hasAuthorReferrerValue())
        {
            $this->sanitizer->sanitizeAuthor();
            $queryVars = $this->handler->getAuthorReferrer();
        }
        if($this->handler->hasDateReferrerValue())
        {
            $this->sanitizer->sanitizeDate();
            $queryVars = $this->handler->getDateReferrer();
        }
        if($this->handler->hasSearchReferrerValue())
        {
            $this->sanitizer->sanitizeSearch();
            $queryVars = $this->handler->getSearchReferrer();
        }
        if($this->handler->hasTaxReferrerValue())
        {
            $this->sanitizer->sanitizeTaxonomy();
            $queryVars = $this->handler->getTaxReferrer();
        }
        return $queryVars; //Will return null if all 4 conditions fail or return the value from the one that returns true
    }
}

class Controller
{
    public function __construct() {}

    public function doStuff(QueryArgumentsInterface $argsClass, QueryVarsInterface $varsClass)
    {
        var_dump($argsClass->queryArguments());
        var_dump($varsClass->queryVars());
    }
}

/*
 * TEST DRIVE
 */

//Create a controller that will use the classes
$controller = new Controller();

//Now make use of your new shiny handlers and sanitizers
$controller->doStuff(
    new ClassA(new RequestReferrerHandler("Mark Twain", null, null, null), new SanitizerForClassA()), 
    new ClassB(new RequestReferrerHandler(null, "January 1st, 1999", null, null), new SanitizerForClassB())
);

$controller->doStuff(
    new ClassA(new RequestReferrerHandler(null, null, "OK Google Now!", null), new SanitizerForClassA()), 
    new ClassB(new RequestReferrerHandler(null, null, null, "Super Awesome Taxonomy Tables"), new SanitizerForClassB())
);

$controller->doStuff(
    new ClassA(new RequestReferrerHandler(null, "January 1st, 1999", null, null), new SanitizerForClassA()), 
    new ClassB(new RequestReferrerHandler("Mark Twain", null, null, null), new SanitizerForClassB())
);

$controller->doStuff(
    new ClassA(new RequestReferrerHandler(null, null, null, "Super Awesome Taxonomy Tables"), new SanitizerForClassA()), 
    new ClassB(new RequestReferrerHandler(null, null, "OK Google Now!", null), new SanitizerForClassB())
);

이전 질문에서 알 수 있듯이 OOP 개발을 합리화할 방법을 모색하고 있습니다.그래서 물고기를 주지 않고 직접 낚시를 도와드리겠습니다.즉, 강력한 OOP 코드를 실행하기 위해 알아야 할 베이스를 제공합니다.

1. SRP 및 조성

질문에서 알 수 있듯이, 당신은 수업의 책임을 분리하려고 합니다.이것은 물론 OOP에서 좋은 것이다.이를 Single Responsibility Principle(SRP; 단일 책임 원칙)이라고 합니다.이 원칙은 상속보다 구성을 선호한다는 것을 의미합니다.

// Composition
class Car implements VehicleInterface
{
    private $motor;
}

class Motor implements MotorInterface

이 경우, 자동차와 모터는 두 가지 다른 역할을 합니다.

// Inheritance
class Car extends MotorVehicle
{

}

상속의 경우 차량과 모터 개념 사이에 높은 합산을 합니다.

예를 들어 다음과 같은 움직임과 같은 새로운 개념을 갖고 싶다고 상상해 보십시오.

// Composition
class Car implements VehicleInterface
{
    private $motor;
    private $movement;
}

class Motor implements MotorInterface

class Drive implements MovementInterface

구도에는 문제가 없습니다.

// Inheritance
class Car extends MotorVehicle, DriveVehicle
{

}

다중 상속은 SRP가 깨지기 때문에 좋지 않습니다(PHP에서는 불가능할 수도 있습니다).상속은 책임이 동일한 클래스의 코드를 인수분해하는 데만 사용해야 합니다.클래스별로 책임이 하나만 있어야 하므로 여러 상속을 사용하면 안 됩니다., 그 이유는 더 수 때문이다.MotorVehicle 훨씬DriveVehicle.

이 경우 Referrer 요청 핸들러와 sanitizer있습니다.

(이) 인터페이스와 저커플링

이전 답변에서 말씀드린 바와 같이 클래스 간에 낮은 결합을 만들기 위해 인터페이스를 사용할 때 올바른 조치를 취하십시오.이를 통해 유지 보수, 확장성 및 테스트 가능한 코드를 얻을 수 있습니다.위의 예를 들어 보겠습니다.

class Car implements VehicleInterface
{
    private $motor;
}

class PetrolMotor implements MotorInterface

class DieselMotor implements MotorInterface

당신의 차는 이제 다른 종류의 모터를 쉽게 가져갈 수 있습니다.

여기서 당신의 마음을 움직여야 할 생각은 클래스가 행동을 기술하는 인터페이스가 아닌 다른 클래스를 직접 사용해서는 안 된다는 것입니다.

ㅇㅇㅇㅇㅇㅇ는class A ★★★★★★★★★★★★★★★★★」class B는, 「」를 가 있습니다.SanitizerInterface.

3. 의존관계 주입

이 시점에서 처리기를 sanitizer로 설정합니다. 좋은 방법은 의존성 주입을 사용하는 것입니다.이건 정말 간단해!

class Car implements VehicleInterface
{
    private $motor;

    public function __construct(MotorInterface $motor)
    {
        $this->motor = $motor;
    }
}

class PetrolMotor implements MotorInterface
{
}

class DieselMotor implements MotorInterface
{
}

$motor = new PetrolMotor();
$car = new Car($motor);

이 경우 referrer 요청 핸들러를 sanitizer에 삽입해야 합니다.

4. SOA

OOP에 적용되는 SOA(Service Oriented Architecture)는 코드를 합리화하는 훌륭한 방법입니다.

// Standard OOP
$car = new Car();
$buyer = new Person();
$store = new Store();

// Many solutions to buy a car!
$buyer->buy($car, $store);
// or
$store->sell($car, $buyer);
// or
// ...

표준 OOP에서는, 그 때문에 중복 코드에 직면하는 일이 자주 있습니다.이 메서드는 어디에 코딩해야 합니까?이 메서드를 이미 코드화한 곳은 어디입니까?전에는 이 문제가 너무 지루했어요!나는 내 개발을 합리화할 수 없었다.

// SOA
$car = new Car();
$buyer = new Person();
$store = new Store();

$saleHandler = new SaleHandler();
$saleHandler->sell($car, $buyer, $store);

클래스여기서는 "서비스 클래스")가 .SaleHandler(싱글톤으로서 실장된 데이터 클래스) (여기서 '데이터 클래스'의 증배를 취급한다.)Car,Person ★★★★★★★★★★★★★★★★★」Store데이터 클래스에는 인텔리전스가 없습니다(많은 경우 속성에 getter와 setter만 있습니다).이렇게 하면 판매 코드가 어디에 있는지 알 수 있습니다.

당신의 경우, 요청하신 레퍼러 핸들러와 세정제는 일종의 서비스인 것 같기 때문에 괜찮습니다.

결론

결론적으로, 당신은 직관적으로 몇 가지 정말 좋은 OOP 프랙티스를 사용합니다.이제 적용해서 이유를 알 수 있습니다!

단, Symfony2와 같은 프레임워크를 사용해 보는 것이 좋습니다.PHP 개발을 위한 강력한 기반과 구성 파일에서 클래스의 모든 종속성을 정의할 수 있는 매우 좋은 종속성 주입 컴포넌트를 제공합니다.또한 서비스를 통해 SOA를 수행하는 데도 도움이 됩니다.

프레임워크를 사용하는 것은, 개발과 프로의 라이프에 박차를 가하기 위해서 좋은 것입니다(프레임을 아는 개발자는, 보다 많은 요구를 받고 있습니다).PHP 프레임워크는 주로 오픈소스이기 때문에 참여하실 수도 있고 모집자가 보기에도 좋습니다.

「」를 하고 .RequestReferrerHandler클래스 A클래스 B클래스 B클래스입니다그러면 당신의 전략이 정확합니다.의 오브젝트만 사용하면 됩니다.RequestReferrerHandlerA-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B-B- 다음 그 즉 '먹다'에 할 수 .ClassA.queryArguments() ★★★★★★★★★★★★★★★★★」ClassB.queryVars()

「」의 개별 .RequestReferrerHandler A 및 Class B의 Class A " Class B " 를 확장할 수 .RequestReferrerHandlerA를 B로 하다하면 ClassA 됩니다.RequestReferrerHandler에서는 속성 및 할 수 .parent:키워드를 지정합니다.예를 들어 다음과 같습니다.

class ClassA extends RequestReferrerHandler
{

public function santizeAuthor()
{

    $author = parent::hasAuthorReferrerValue();  // access the base class method

    if ($author) {
        $author = array_values($author);
        $author = ['author' => (int)htmlspecialchars($author[0])]; //Will output ['author' => 1]
    }

    return $author; //Returns null or the array ['author' => 1]
}

public function santizeDate()
{
    $date = parent::hasDateReferrerValue();

    if ($date) {
        // @TODO Still to work out
    }

    return $date;
}

//etc

public function queryArguments() // Will be used in the controller class ClassC
{
    $queryArgs = null;

    if ($this->santizeAuthor()) {

        $queryArgs = $this->santizeAuthor();

    } elseif ($this->santizeDate) {

        $queryArgs = $this->santizeDate();

    } // etc
    return $queryArgs; //Will return null if all 4 conditions fail or return the value from the one that returns true
}

}

클래스 B: 클래스 B입니다.A 및 C를 할 수 .ClassA.queryArguments() ★★★★★★★★★★★★★★★★★」ClassB.queryVars()상으으대

Wordpress 구조를 조작하고 정보를 얻을 수 있는 API에서 작업하던 객체의 의미 대신 데이터 유형에 집중한다면 이 문제는 단순화될 수 있습니다.또한 이미 데이터 구조를 단순화하는 매우 훌륭한 작업을 한 것으로 알고 있습니다.그래서 포스트, 포스트 메타, 분류법(인덱스)에서만 생각하면 되고, 출판, 세금, 이미지, 도서관, 포스트, 제품 등의 의미에서는 생각하지 않으면 된다.

심지어 woo commerce에서도 그것은 매우 단순하다는 것을 알 수 있다.

제품이 포스트 메타에 있는 경우, 제품의 데이터가 포스트 메타에 있는 경우, 이미지가 포스트 메타에 있는 경우, 해당 이미지의 상세 내역이 포스트 메타에 있는 경우, 뉴스가 포스트임을 알 수 있습니다.

하나의 구조가 다른 의미입니다.이 요소만 있으면 모든 데이터에 액세스하거나 데이터를 저장할 수 있습니다.구현이 매우 쉬운 방법으로 이 요소에 액세스할 수 있는 경우

나는 이것이 당신에게 도움이 되기를 바랍니다. 당신이 다르게 생각할 수 있는 나의 관점이기도 합니다.하지만 그 사람을 당신과 공유하는 게 중요하다고 생각했어요

언급URL : https://stackoverflow.com/questions/28704514/interface-injection-and-common-classes

반응형