Php 使用多态性和工厂模式消除重复条件
如果IndexView代码实际上是相同的,那么您不需要继承,而是需要组合。在基本LayoutView类中添加一个IndexView实例,然后可以从每个*LayoutView调用该实例 仅当对象之间的关系为-a时,继承才到期。我推断IndexView不是LayoutView,而是LayoutView有一个IndexView 看看这个,我并不完全同意它所说的一切,但仍然:Php 使用多态性和工厂模式消除重复条件,php,oop,design-patterns,inheritance,refactoring,Php,Oop,Design Patterns,Inheritance,Refactoring,如果IndexView代码实际上是相同的,那么您不需要继承,而是需要组合。在基本LayoutView类中添加一个IndexView实例,然后可以从每个*LayoutView调用该实例 仅当对象之间的关系为-a时,继承才到期。我推断IndexView不是LayoutView,而是LayoutView有一个IndexView 看看这个,我并不完全同意它所说的一切,但仍然: 只需将模板作为参数传递给要编写的子视图即可。我不认为在这种情况下那是邪恶的。虽然如果这是一个标准框架,你最好在他们的论坛上提问,
只需将模板作为参数传递给要编写的子视图即可。我不认为在这种情况下那是邪恶的。虽然如果这是一个标准框架,你最好在他们的论坛上提问,因为他们可能有一个我们在这种情况下不知道的功能(通常会发生) 你可以吃点像这样的东西
<?php
/**
* My codebase is littered with the same conditionals over and over
* again. I'm trying to refactor using inheritance and the Factory
* pattern and I've had some success but I'm now stuck.
*
* I'm stuck because I want to derive a new class from the one
* returned by the Factory. But I can't do that, so I'm obviously
* doing something wrong somewhere else.
*/
/**
* The old implementation was as follows. There's if statements
* everywhere throughout both LayoutView and ItemIndexView and
* SomeOtherView.
*/
class LayoutView { }
class IndexView extends LayoutView { }
class SomeOtherView extends LayoutView { }
/**
* Below is the new implementation. So far I've managed to tidy
* up LayoutView (I think I have anyway). But now I'm stuck because
* the way I've tidied it up has left me not knowing how to extend
* it.
*
* For example's sake, let's say the conditions were relating to a
* type of fish: salmon or tuna.
*/
abstract class LayoutView {
protected function prepareHeader() { echo __METHOD__, "\n"; }
protected function prepareLeftHandSide() { echo __METHOD__, "\n"; }
protected function prepareFooter() { echo __METHOD__, "\n"; }
public function prepare() {
$this->prepareHeader();
$this->prepareLeftHandSide();
$this->prepareFooter();
}
}
class SalmonLayoutView extends LayoutView
{
protected function prepareLeftHandSide() { echo __METHOD__, "\n"; }
}
class TunaLayoutView extends LayoutView
{
protected function prepareLeftHandSide() { echo __METHOD__, "\n"; }
protected function prepareFooter() { echo __METHOD__, "\n"; }
}
class ViewFactory {
public static function getLayoutView($fishType) {
switch($this->$fishType) {
case 'salmon':
return new SalmonLayoutView();
break;
case 'tuna':
return new TunaLayoutView();
break;
}
}
}
/**
* Now LayoutView has been cleaned up and the condition that was once
* scattered through every LayoutView method is now in one place.
*/
$view = ViewFactory::getLayoutView( Config::getOption('fishtype') );
$view->prepare();
/**
* Now here's where I'm stuck. I want to effectively extend whatever
* class $view is an instance of.
*
* The reason being, I wish to derive a view to show an index of
* articles within the appropriate *LayoutView. The IndexView code is
* the same for Salmon and Tuna.
*
* I can do something like this:
*/
class SalmonIndexView extends SalmonLayoutView { }
class TunaIndexView extends TunaLayoutView { }
/**
* But then I'll be writing the same IndexView code twice. What I'd
* like to do is something like this:
*/
$view = ViewFactory::getLayoutView( Config::getOption('fishtype') );
class IndexView extends get_class($view) { }
/**
* But I'm pretty certain that's not possible, and even if it was
* it seems very wrong.
*
* Can someone more experienced in refactoring and OO please let
* me know where I've gone wrong and suggest a clean way to solve
* this?
*/
顺便说一句,将这个非常有效的编程问题标记为社区wiki只会让人对它关注较少。
class LayoutView {
protected View $subview; //Potentially an array of views
public function prepare() {
// empty, to be filled out by derived classes
}
public function setSubView($view) { $this->subview = $view; }
public function display() {
$this->prepare();
$this->subview->prepare($this->template);
$this->template->render();
}
}
class IndexView {
protected View $subview; //Potentially an array of views
public function prepare() {
// empty, to be filled out by derived classes
}
public function prepare($template) {
//operate on it, maybe even assigning it to $this->template
}
public function setSubView($view) { $this->subview = $view; }
public function display() {
$this->prepare();
$this->subview->prepare($this->template);
$this->template->render();
}
}