我有一个关于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
。有没有更好的方法,不使用静态方法。
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中,您始终可以添加其他方法来处理创建新视图的逻辑。