newable /注射用ジレンマなViewHelper
-
20-09-2019 - |
質問
私は<のhref = "http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/" のrel = "nofollowを、以下のアプリケーションを設計しようとしていますnoreferrer "> Misko Heverysの洞察がを。それは興味深い実験と挑戦です。現在、私は私なViewHelper実装に苦しんでいます。
なViewHelperは、ビューからモデルを分離します。私の実装では、モデルをラップし、使用するビューのためのAPIを提供します。私はPHPを使用していますが、私は実装が皆のための読みであると思います:
class PostViewHelper {
private $postModel;
public function __construct(PostModel $postModel) {
$this->postModel = $postModel;
}
public function title() {
return $this->postModel->getTitle();
}
}
私のテンプレート(ビュー)このファイルには次のように呼び出すことができます:
<h1><?php echo $this->post->title(); ?></h1>
これまでのところは良いです。私はViewHelpersにフィルタを添付したいときに私が持っている問題があります。私はタイトルの()の呼び出しの出力をフィルタリングするプラグインを持っていると思います。方法は次のようになります。
public function title() {
return $this->filter($this->postModel->getTitle());
}
私はそこでのオブザーバー、またはイベントハンドラ、または任意のサービスを取得する必要があります(私はnewableとして見るもので、それは、スタックを介して渡される必要があります)。どのように私はMisko Heveryの原則以下、これを行うことができますか?私はそれなしでこれを行うことができます方法を知っています。私はそれを取ることができ、現在、私は解決策が表示されないためにどのように興味があります。 ViewHelperデコレータは、あまりにも、注射することが、その後問題があるモデルを得ることができます。
解決
私はあなたが非常に興味深い洞察力に富んまたは参照ブログ記事を見つけることができませんでした。
あなたが記述していることは、より依存性の注入を行うには何よりもデコのように思えます。依存性の注入は、の方法は、あなたのオブジェクトグラフを構築ない自分の状態を一度構築します。
私はあなたのDecoratorパターンを取り、それを実行することをお勧めしたい、と述べています。
interface PostInterface
{
public function title();
}
class PostModel implements PostInterface
{
public function title()
{
return $this->title;
}
}
class PostViewHelper implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->post = $post;
}
public function title()
{
return $this->post->title();
}
}
class PostFilter implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->post = $post;
}
public function title()
{
return $this->filter($this->post->title());
}
protected function filter($str)
{
return "FILTERED:$str";
}
}
あなたは、単にあなたがそうのように、このオブジェクトグラフを構築する必要がどのようなDIフレームワークを使用したいです
$post = new PostFilter(new PostViewHelper($model)));
複雑なネストされたオブジェクトを作成するときに私は、多くの場合、このアプローチを使用しています。
あなたがに実行する可能性がある問題の一つは、あなたのPostInterface
に「あまりにも多くの」関数を定義しています。 のすべてのデコレータのクラスでこれらを実装する必要がありますするの痛みをすることができます。私はこの問題を回避するためにPHPの魔法の機能を活用する。
interface PostInterface
{
/**
* Minimal interface. This is the accessor
* for the unique ID of this Post.
*/
public function getId();
}
class SomeDecoratedPost implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->_post = $post;
}
public function getId()
{
return $this->_post->getId();
}
/**
* The following magic functions proxy all
* calls back to the decorated Post
*/
public function __call($name, $arguments)
{
return call_user_func_array(array($this->_post, $name), $arguments);
}
public function __get($name)
{
return $this->_post->get($name);
}
public function __set($name, $value)
{
$this->_post->__set($name, $value);
}
public function __isset($name)
{
return $this->_post->__isset($name);
}
public function __unset($name)
{
$this->_post->__unset($name);
}
}
使用中のデコレータのこのタイプでは、私が選択的に、私は装飾された機能を提供するために必要なものは何でもメソッドオーバーライドすることができます。私はオーバーライドしないものは、基礎となるオブジェクトに戻されます。基礎となるオブジェクトのインターフェースを維持しながら、複数の装飾がすべて発生する可能性があります。