具有实现系统的多个提供者,设计模式使用

时间:2014-12-09 21:07:22

标签: design-patterns

我正在尝试确定用于全文搜索服务的最佳设计模式。我想象的基本逻辑如下所示,也有要点:https://gist.github.com/qutwala/1b574a39286a7525c8c7 当我调用search()方法时,它应该通过配置决定哪个搜索引擎(Sphinx,Solr等)以及该引擎要加载的实现(Local,API。)。

我不确定使用什么样的设计模式。起初,我认为可能涉及 Factory Singleton 设计模式。

根据我目前的实施情况,我发现以下问题:

  • 如何设置以及何时将所有属性类注入某个实现。
  • 如何在某些实施中访问属性。
  • 我想可能会有更多这些,直到它不是刺激。 :)

正如我之前提到的,我对使用模式的正确方式感兴趣,所以欢迎任何想法评论。

代码:

<?php

Interface SearchEngine
{
    public function getSearchProperties();

    public function setSearchProperties(SearchProperties $properties);

    public function getImplementation($implementation);
}

Interface SearchPropertiesInterface
{
    public function setIndex($index);
}

class SearchProperties implements SearchPropertiesInterface
{
    private $properties = array();

    public function setProperty($property, $value) {
        echo "Set property <br />";
        $this->properties[$property] = $value;
    }

    public function setIndex($index) {
        $this->setProperty('index', $index);
    }
}

class SphinxSearchEngine implements SearchEngine
{
    private $SearchProperties;

    public function __construct()
    {
        $this->SearchProperties = new SearchProperties();
    }

    private $implementations = array();

    /**
     * @param $implementation
     *
     * @return SphinxSearchImplementation
     */
    public function getImplementation($implementation)
    {
        echo "Returned SphinxSearchEngineAPIImplementation <br />";
        // TODO: on demand load a.ka. singleton?
        $this->implementations[$implementation] = new SphinxSearchEngineAPIImplementation();

        return $this->implementations[$implementation];
    }

    /**
     * TODO: how to inject properties?
     * TODO: what if changed implementation, should be injected in both?
     *
     * @return SearchProperties
     */
    public function getSearchProperties()
    {
        return $this->SearchProperties;
    }

    public function setSearchProperties(SearchProperties $properties)
    {

    }
}

Interface SphinxSearchImplementation
{
    public function search($query, $limit, $offset);
}

class SphinxSearchEngineAPIImplementation implements SphinxSearchImplementation
{
    public function search($query, $limit, $offset) {
        //TODO: how to get properties, index?
        echo "Find results by SphinxSearchEngineAPIImplementation <br />";
    }
}

class ElasticSearchEngine implements SearchEngine
{
    private $implementations = array();

    public function __construct()
    {
        $this->SearchProperties = new SearchProperties();
    }

    /**
     * @param $implementation
     *
     * @return SphinxSearchImplementation
     */
    public function getImplementation($implementation)
    {
        return $this->implementations[$implementation];
    }

    public function getSearchProperties()
    {
        return $this->SearchProperties;
    }

    public function setSearchProperties(SearchProperties $properties)
    {
        // TODO: how to inject properties?
        // TODO: what if changed implementation, should be injected in both?
    }
}

class Search
{
    public function __construct() {
        // magic goes here :)
    }

    private $config = array(
        "engine"    =>  "Sphinx|ElasticSearch"
    );

    public function getEngine()
    {
        echo "Loaded engine: Sphinx <br />";
        return new SphinxSearchEngine(); // For example by config loaded sphinx SE?
    }

    public function search($query, $limit, $offset) {
        // TODO: how to decide which engine to use?
        // TODO: engine should have own properties set?

        $this->getEngine()->getSearchProperties()->setIndex('search_index');

        try {
            $this->getEngine()->getImplementation('local|api')->search($query, $limit, $offset);
        } catch (Exception $e) {
            // TODO: What to do now, fallback to another engine?
        }
    }
}

$search = new Search();
$search->search('my search query', 10, 0);

1 个答案:

答案 0 :(得分:0)

我认为,策略模式正是您所寻找的 因此,您将拥有工厂类,您可以在任何标志之间切换 如下所示:

class Factory()
{
     public Factory CreateFactory(Enum parameter)
     {
        Factory manager = null;
        switch(parameter)
        {
           case 1:
              manager = new ImplementationOne();
              break;
           case 2:
              manager new ImplementationTwo();
              break;
           else:
              break;
        }         
        return manager;
     }     
}

然后,您可以像往常一样拥有ImplementationOne类等。

参考: Strategy Pattern

谢谢,