15

ActiveRecordBaseModelクラスと、それを継承する多くのクラス モデルがあります。そして、私は同様Bookmarkに継承さBaseModelれたクラスを持っています。また、継承されたクラスがあります。これらは、単一のモデル (メソッド)Decoratorを表す特別なインターフェイスを実装しています。getModelView(model)これはいくつかの疑似コードです:

TestModel inherits BaseModel
    getName:
        return this.name

BookmarkModel inherits BaseModel
    BaseModel model

    getBookmark:
        return this.model

TestDecorator inherits BaseDecorator implements SingleModelViewInterface:
    getView(model):
        return 'view' //html-view of model

BookmarkDecorator inherits BaseDecorator
    getBookmarksView(BookmarkModel[] bookmarks):
        foreach(bookmarks > bookmark):
            decorator = Relation::getDecoratorByModel(bookmark->getEntityType())
            decorator->getView(bookmark->getBookmark())

したがって、ブックマークされたモデルのビューを少し変更するまで、すべてがうまく見えます。そのビューのカスタム タイトルを追加したい。そして、ブックマークだけでなくレンダリングするため、デコレータ内で作成することはできません。

編集:だから、問題は-デコレータパターンが必要なようですが、TestModelの特別なメソッドを使用する具体的なTestDecoratorがあるため、継承するものは何もありません。だから今、私は魔法の方法(PHP)を使用して、いくつかの本当に悪い認識をしました:

class BookmarkedModel {

    /** @var BaseEntityModel*/
    private $model;

    public function __construct(BaseEntityModel $model) {
        $this->model = $model;
    }

    public function getName() {
        return 'Bookmark '.$this->model->getName();
    }

    public function __call($name, $arguments) {
        return call_user_func_array(array($this->model, $name), $arguments);
    }

    public function __get($name) {
        return $this->model->$name;
    }

    public function __set($name, $value) {
        return $this->model->$name[$value];
    }

}

今のところはうまくいきますが、コード構造、可読性、および安定性の観点から、これは本当に悪い決定です。

4

1 に答える 1

2

モデルはビューを認識しない必要があります。モデルは、一度にあらゆる角度から見た生データを表します。ビューはそのモデルのパースペクティブです。コントローラーは、モデルをビューにフィードする必要があります。

$model_view->render($model);

次に、ビューを装飾します。

$bookmark_view->render($model); // bookmark_view wraps a model_view,
// returns 'Bookmark '.$this->model_view->render($model)

型ではなく、インターフェイスに基づいてのみ装飾します。

PHP のマジック メソッドは優れていますが、ActiveRecord には使用しないでください。これは「関心の分離」に反します。この場合、モデルを永続化メカニズムから分離します。

代わりに、ActiveRecord オブジェクトを作成し、それにモデルフィードします。

$record->store($model);

次に、ストレージを変更する必要がある場合は、ストレージ メカニズムをデコレートします。

$log_record->store($model); // wraps $record, logs a message prior to database storage.
于 2013-05-11T14:47:18.557 に答える