4

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 にフィルターをアタッチしたいときです。title() 呼び出しの出力をフィルタリングするプラグインが必要です。メソッドは次のようになります。

public function title() {
    return $this->filter($this->postModel->getTitle());
}

そこにオブザーバー、EventHandler、またはその他のサービスを取得する必要があります (newable と見なされるため、スタックを介して渡す必要があります)。Misko Hevery の原則に従ってこれを行うにはどうすればよいですか? 私はそれなしでこれを行う方法を知っています。どうやってそれを取ることができるかに興味がありますが、現在、解決策がわかりません。ViewHelper も注入可能ですが、そこにモデルを取得することが問題です。

4

1 に答える 1

4

あなたが参照したブログ投稿が非常に興味深く、洞察に満ちているとは思いませんでした。

あなたが説明していることは、依存性注入に関係する何よりもデコレータのように見えます。依存性注入は、オブジェクトグラフを作成する方法であり、作成された後の状態ではありません。

そうは言っても、デコレータパターンを使用して実行することをお勧めします。

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)));

複雑なネストされたオブジェクトを作成するときに、このアプローチをよく使用します。

発生する可能性のある問題の1つは、で「多すぎる」関数を定義することです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);
    }
}

このタイプのデコレータを使用すると、装飾された機能を提供するために必要な方法を選択的にオーバーライドできます。オーバーライドしないものはすべて、基になるオブジェクトに戻されます。基になるオブジェクトのインターフェイスを維持しながら、複数の装飾をすべて行うことができます。

于 2010-02-05T18:07:19.943 に答える