ViewHelper 可更新/可注入的困境

2024-02-04

我正在尝试设计以下应用程序米斯科·赫弗里斯的见解 http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/。这是一个有趣的实验,也是一个挑战。目前我正在为 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());
}

我需要在那里获取观察者,或者事件处理程序,或者任何服务(在我看来是可更新的,所以它需要通过堆栈传入)。我怎样才能遵循 Misko Hevery 的原则做到这一点?我知道没有它我怎么能做到这一点。我对如何接受它很感兴趣,但目前我没有看到解决方案。 ViewHelper 也可以是可注入的,但是将模型放入其中就会出现问题。


我没有发现您引用的博客文章非常有趣或富有洞察力。

你所描述的似乎更像是装饰者 http://en.wikipedia.org/wiki/Decorator_pattern比任何与依赖注入有关的事情都重要。依赖注入是how你构建你的对象图,而不是它们的state一旦建成。

也就是说,我建议采用装饰器模式并运行它。

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。它可以是一个pain必须在每个装饰器类中实现这些。我利用 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);
    }
}

使用这种类型的装饰器,我可以有选择地重写提供装饰功能所需的任何方法。我没有覆盖的任何内容都会传递回底层对象。在维护底层对象的接口的同时,可以发生多个装饰。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ViewHelper 可更新/可注入的困境 的相关文章

  • 搜索文本后去掉 Vim 的高亮显示

    在 VIM 中 使用 命令查找文本后 该文本保持突出显示状态 删除它的命令是什么 我根本不想删除突出显示功能 但一旦找到我需要的内容 我又不想拥有所有这些明亮的文本点 Thanks 输入 noh
  • SQL-根据列组合连续的日期行

    假设我有以下 SQL 结果 BegDate EndDate quanitty 1 1 2014 1 31 2014 1 2 1 2014 2 28 2014 1 3 1 2014 3 31 2014 2 4 1 2014 4 30 2014
  • AngularJS $resource GET 中的多个参数

    use strict angular module rmaServices ngResource factory rmaService resource function resource return resource RMAServer
  • 编译先前预处理的文件会更改输出

    我有一个源文件 我使用选项对其进行预处理 E and P 对于基于 vxWorks 的嵌入式平台使用 GCC 4 1 2 所有其他选项与我编译文件时相同 这些选项是 Wall march pentium nostdinc O0 fno bu
  • 在 matplotlib 中打开灯

    我有以下Python代码 import numpy as np from matplotlib import pyplot as plt plt rcParams figure figsize 12 7 n 100 m 100 X np a
  • 在 Xcode 中打开权利会阻止 Bare Bones 应用程序启动

    我在 Xcode 4 2 中创建了一个基本应用程序 非常简单的应用程序 我没有改变任何东西 按下运行 您将获得标准的基本应用程序窗口 如果我打开目标的权利并点击运行 我不会收到任何调试器错误 但窗口永远不会出现 我使用 Console ap
  • 当关联计数更改时强制更新 NSFetchedResultsController

    我有一个 NSFetchedResultsController 它在表视图中显示项目列表 包括关联实体的计数 当为此关联添加对象时 使用 addXXXObject 不会调用回调来通知我的控制器更新 如何接收对象被添加到父实体的 NSSet
  • Java Beans Binding 的状态如何?

    我发现一篇旧文章http www artima com lejava articles beans binding html http www artima com lejava articles beans binding html以及一
  • 针对单个客户端请求并行多个数据库查询

    为了完成用户的某些请求 在我的应用程序中 我从单个方法发出多个数据库查询 但它们当前正在按顺序执行 因此应用程序被阻止 直到它收到前一个查询的响应 数据 然后继续下一个查询 这不是我很喜欢的事情 我想发出并行查询 另外 在发出查询之后 我想
  • 使用 ffmpeg 在同一张图像上使用两次淡入/淡出

    我使用此命令在流开始 5 秒后淡入徽标 并在 25 秒后淡出 如下所示 ffmpeg re i test mp4 ignore loop 0 i logo gif filter complex 1 v fade in st 5 d 1 al
  • 在 QML 中截取特定项目的屏幕截图的方法是什么?

    我知道如何在 QML 中截取整个窗口的屏幕截图 https stackoverflow com questions 33165733 qquickwindowgrabwindow scene graph already in use lq
  • “onclick”不适用于具有 svg-image 的对象元素[重复]

    这个问题在这里已经有答案了 当我使用onclick的属性object html 文档中的元素 它不响应点击 在我的文档中 我有一个 svg 图像并将其存储在object element 因为图像中存在一些动画 仅使用img tag 在下面的
  • Silverlight:画布溢出

    我创建了一个 Canvas 并在其中放置了一个 StackPanel StackPanel 是水平的 它接受缩略图列表 画布有固定的大小 当我放置的缩略图数量超过 Canvas 宽度可以容纳的数量时 StackPanel 应该会从 Canv

随机推荐