在运行时未知类类型时,使用带有控制反转的工厂方法

时间:2018-03-06 10:39:50

标签: php oop design-patterns dependency-injection inversion-of-control

我对IOC有疑问,当我不知道要在运行时实例化的类时。例如,我有几种类型的View类。 (HtmlView,CsvView,PDFView等)实现我的视图界面。我需要的视图类的类型由用户输入(DB中的字符串)决定。我倾向于使用具有make方法的ViewFactory类,问题是这将隐藏View依赖项,因为我只需要ViewFactory

   class ViewFactory{
        public function make($viewType){
              if($viewType == 'html'){
                 $view = new HtmlView();
              }
              // ...
              return $view   
        }
   } 

   class ReportGenerator{
           public function constructor(Array $data, ViewFactory $viewFactory, String $viewType ){
                 $this->data = $data;
                 $this->view = $viewFactory($viewType);
           }
           public function generate(){
                  return $this->view->render($this->data)
           }
   }   

在我看来,ReportGenerator取决于基础ViewInterface并不清楚。有没有更好的方法,不使用静态方法。

1 个答案:

答案 0 :(得分:0)

interface ViewInterface {

  public function render();
}

class HtmlView implements ViewInterface {

  const HTML_VIEW = 'html';

  public function render() {
    // TODO: Implement render() method.
  }
}

class AnotherView implements ViewInterface {

  const ANOTHER_VIEW = 'another';

  public function render() {
    // TODO: Implement render() method.
  }

}

class ViewFactory {

  public static function make($viewType) { // this could also be static
    // or use a construct, whichever strikes your fancy
    if ('html' == $viewType) { // fan of Yoda metod, I am
      $view = new HtmlView();
    }
    // ...
    return $view;
  }
}

class ReportGenerator {

  private $data;
  private $view;

  public function constructor(array $data, ViewInterface $view) {
    $this->data = $data;
    $this->view = $view;
  }

  public function generate() {
    return $this->view->render($this->data);

  }
}


$view = ViewFactory::make(HtmlView::HTML_VIEW);


$report = new ReportGenerator([], $view);

不要让ReportGenerator处理任何与之相关的视图,而是必须传递已经创建的视图。

视图本身应该在ReportGenerator之外创建(或者任何其他类 - ViewFactory除外)。

在ViewFactory中,您始终可以添加其他方法来处理创建新视图的逻辑。