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