Jih*_*Han 5 mvp design-patterns presenter-first
我最近发现了Presenter First并阅读了他们的白皮书和博客等.
在我发现的大多数示例中,事件不是直接在接口上声明,而是作为它的方法.例如,
public interface IPuzzleView
{
void SubscribeMoveRequest(PointDelegate listener);
// vs
event PointDelegate MoveRequest;
}
Run Code Online (Sandbox Code Playgroud)
我不明白为什么.我以为我在某个地方看到了一篇文章/文章/博客,解释了这背后的原因,但我再也找不到了.所述文本还包含单元测试代码的片段 - 我知道这是因为我记得对自己说,其中一个单元测试是不正确的.
更新:
以下是比较示例:
public class Collect
{
public static CollectAction<T> Argument<T>(int index,
CollectAction<T>.Collect collectDelegate)
{
CollectAction<T> collect = new CollectAction<T>(index, collectDelegate);
return collect;
}
}
public interface IApplicationView
{
event EventHandler Load;
// or
void SubscribeLoad(Action action);
}
Mockery mockery = new Mockery();
IApplicationView view = mockery.NewMock<IApplicationView>();
IApplicationModel model = mockery.NewMock<IApplicationModel>();
Run Code Online (Sandbox Code Playgroud)
订阅风格:
Action savedAction = null;
Expect.Once.On(view).Method("SubscribeLoad").Will(
Collect.Argument<Action>(0,
delegate(Action action) { savedAction = action; }));
Expect.Once.On(model).Method("LoadModules");
new ApplicationPresenter(view, model);
savedAction();
mockery.VerifyAllExpectationsHaveBeenMet();
Run Code Online (Sandbox Code Playgroud)
与事件:
Expect.Once.On(view).EventAdd("Load", Is.Anything);
Expect.Once.On(model).Method("LoadModules");
new ApplicationPresenter(view, model);
Fire.Event("Load").On(view);
mockery.VerifyAllExpectationsHaveBeenMet();
Run Code Online (Sandbox Code Playgroud)
仅供参考,上面的事件样式将无法正常工作,因为ApplicationPresenter会立即收集垃圾并且布线永远不会发生.
小智 4
简短的回答是:Presenter First 最初是在 .NET 1.1 和 VS2003 时代发展起来的,C# 事件可能会出现问题。
当时的测试/模拟工具不支持我们封装事件订阅和分派的需要。随着时间的推移,我们逐渐感觉到,将事件的特定性质暴露在其发出类之外会给客户端代码带来太多的实现知识负担,这使得重构变得困难。
对于已发布的示例,我们希望避免将 Presenter First 技术与特定于语言的功能相关联。(例如,Java 没有与 C# 事件或委托等效的功能,但这并不意味着您不能使用观察者模式。)
我看到事件、匿名代表和模拟工具在过去几年中取得了长足的进步。下次我选择 C# 项目时,我将重新评估我对处理事件订阅和分派的“最佳方式”的所有假设。上面的例子很有趣。
总结一下我们隐藏 C# 事件使用的最初(也许已经过时)的原因: - 在单元测试中不可能模拟事件订阅 - 有时我们会使用不同的内部机制来处理事件订阅/分派。这导致了一个接口与另一个接口的不一致。- 我们多次考虑甚至在内部放弃 C# 事件,因为当不存在订阅者时它们的行为有所不同。将事件暴露在外部会使重新实施变得更加困难。
当 Jiho Han 向我发消息询问这个问题时,他还询问了有关数据绑定和更充实的 PF 示例的信息,我对此的回应是发布了更新、更完整的 Presenter First 示例并详细阐述了 Adapters。