热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

接口注入和通用类

如何解决《接口注入和通用类》经验,为你挑选了1个好方法。

我试图了解OOP原则并编写自己的类.作为一种学习方法,我决定将我在Wordpress中编写的一些函数转换为OOP类.这些功能一起工作,以便根据URL中设置的引用(其中4个)在单个页面上输出正确的帖子链接.

这是具有基本工作流程的设置(工作流程可以随着我的进展而改变):

在此输入图像描述

根据归档页面将4个查询变量设置为URL,即,分类页面的一个查询变量,为作者页面设置的一个查询变量等等.任何页面都不能有多个自定义查询变量.在这种情况下,这4个变量由我的第一个类检索并针对给定的全局变量进行检查$_GET.我没有硬编码我的类中的4个变量,这$_GET也是为了保持类可测试.如果URL中存在该值,则通过has*方法返回键/值对.null如果未找到匹配项,则返回这些方法.(这是将使用此数据的类清理/转义的原始数据)

这是完整的课程

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');
?>
hasAuthorReferrerValue()); ?>
hasDateReferrerValue()); ?>
hasSearchReferrerValue()); ?>
hasTaxReferrerValue()); ?>

出于测试目的,您可以将类似的东西注入['aq' => '1']到类中而不是$_GET

这就是我现在被困住的地方,不知道如何继续前进.我需要构造两个类,它们都使用上面类中的相同方法,一个类has*将从上面的类中的方法构造查询参数,并且一个类query_vars也将从has*上面将要使用的类的方法创建构建新的帖子链接

因此,简而言之,两个类都将使用与上述类中的方法完全相同的类

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

举个例子,这里有两个类应该是什么样子的例子.(我在这里省略了一些方法来使代码更易于管理)

ClassA的

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
    }

}

ClassB的

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()从方法ClassAqueryVars()从方法ClassB将在其他类(或一个控制器类)一起使用

我完全缺乏适当的知识进入OOP,混淆分离关注点,封装,SOLID原则和保持类可测试让我第二次猜测我的代码,我觉得我错过了一些东西.

无论如何,我可以优化上述内容.我不是要求任何类型的代码重写,我需要的是关于优化这一点的正确指针和想法,如果不是,则将其提升到标准.如果任何人都可以提供代码示例,例如大纲骨架,这将是一个真正的加分



1> Crackertasti..:

查看您的代码,您肯定是一个良好的开端.在OOP编程时,您已经使用了一个好的经验法则 - 编程到接口,而不是实现. 通过术语接口,我不是仅指实际接口,而是指抽象类.

因此,在您的问题的核心,您希望有两个类,ClassA并且ClassB都使用常用方法RequestReferrerHandler.您已经完成了基于界面的基础工作RequestReferrerHandlerInterface.所以我们会说你有一个如下所示的界面:

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

So long as this interface is implemented by the RequestReferrerHandler you can type hint the interface as the constructor requirements for ClassA and ClassB. But this isn't anything new because you were already doing this.

There are two things in particular that stand out at me as potential sore thumbs. First, since you want the responsibilities of your classes to be small, you should take the responsibility of providing data to the RequestReferrerHandler away from itself and give it to your Controller. In other words, do not inject $_GET into your class. Make sure your Controller has all the information it needs to properly create the RequestReferrerHandler Let's take a look at your RequestReferrerHandler class, flushed with all of the methods it will need.

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()方法.你看他们是如何在这两个复制ClassAClassB?该sanitizeAuthor()是两个阶级之间的不同,但对其余的怎么样?这是DRY (不要重复自己)原则可以帮助的情况.由于多个类可能必须以类似的方式清理数据,因此从类中抽象出来是有意义的.

让我们来看看如何做到这一点然后我们将回到你的具体课程.首先创建一个新接口,该接口将指定必须由可以清理数据的对象公开的方法.

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

现在,如果您拥有的每个对象ClassX以不同的方式实现这四种方法,您就可以开始在不同的类中实现它,只需清理数据.但是,对于这个例子,我们会说并非如此.让我们作一个假设,sanitizeAuthor()可能是中不同的ClassAClassB(它是在你的代码)和所有其他方法将被执行完全一样的.这种情况下我们可以使用一个实现清理方法的抽象类.

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

}

Some things to take note of right off the bat. First, you'll notice there is the setHandler() method which accepts an instance of the RequestReferrerHandlerInterface. Why is this there? Convenience for the most part. Since we have taken the sanitizing behavior and encapsulated it into its own class it would be nice it we gave the sanitizer a way to update the concrete RequestReferrerHandler it is using with the updated output from a sanitize method.

接下来,我们使用的是RequestReferrerHandler类中未指定的方法RequestReferrerHandlerInterface.这不是一个现实的问题本身,因为我们知道,像getter和setter方法是在类.但是,如果您决定使用不同的具体对象实现该接口,则单独对接口进行类型提示并不能保证这些方法可用.因此,我们需要更新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并且ClassB将以sanitizeAuthor()不同方式实施他们的方法.抽象类AbstractSanitizer是按照它的方式制作的,因为sanitizeAuthor()来自它的方法SanitizerInteface没有实现,AbstractSanitizer因此我们必须扩展它以提供功能.我们需要以下两个类来执行此操作:

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

这两个具体类可以与将要传递给它们的具体方法中的数据一起使用ClassAClassB清理RequestReferrerHandler.

继续,让我们来看看规格ClassAClassB.我们知道ClassA将需要该方法queryArguments(),ClassB将需要该方法,queryVars()并且这两个类将需要允许和实例a RequestReferrerHandlerInterfaceSanitizerInterface在其构造函数中.我们将使用一个接口处理构造函数需求,然后另外两个接口将扩展它以提供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
    }
}

There you have it, the ground work is built. You'll notice that in the constructors properties are set for the handler and sanitizer class that was given and then the sanitizer is given the reference to the handler. (Remember, the sanitizers have a reference to the handler so that sanitized properties in the handler are automatically updated. The individual classes don't need to worry about that now.)

So now the million dollar question is how to use this. Well, you need a controller that can accept ClassA and ClassB. We will type hint these by their respective interfaces as well.

class Controller
{
    public function __construct() {}

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

在您的版本queryArguments()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())
);

这是输出:

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个抽象类和一些具体的类来向屏幕输出一些数据.

What do you gain? Short answer - flexibility. In the future you may wish to add more classes that implement either the QueryVarsInterface or QueryArgumentsInterface. Consider these classes ClassC, ClassD and ClassE. All of these classes will need a sanitizer class to go with them (that is if SanitizerForClassA or SanitizerForClassB do not fit the bill) and it would be tedious to keep having to write sanitizer classes. Well, good thing for you, since you were programming to an interface all along, you won't have that problem. You can easily make a GenericSanitizer with a default implementation of the sanitizeAuthor() method. Use can use this class with Controller::doStuff() in any case where you don't need a specialized sanitizer class. You could just as easily implement different concrete classes of QueryArgumentInterface or QueryVarsInterface to test out experimental features you want to add without tampering with your current classes.

Hopefully this has given you some insight on some OOP principles. Here is a complete copy of all of the code above. Slap this in an empty PHP file and run it to see everything in action. Happy programming!

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


推荐阅读
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • CEPH LIO iSCSI Gateway及其使用参考文档
    本文介绍了CEPH LIO iSCSI Gateway以及使用该网关的参考文档,包括Ceph Block Device、CEPH ISCSI GATEWAY、USING AN ISCSI GATEWAY等。同时提供了多个参考链接,详细介绍了CEPH LIO iSCSI Gateway的配置和使用方法。 ... [详细]
author-avatar
书友36110188
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有