分离域与表示 - 第三部分
关于“分离域与表示”系列文章的第三篇。
来自 IRefactor 的转载
这是关于“分离领域与表现”重构的系列文章的第三篇。
之前的文章
上次,我们解释了如何重构为 MVP – Supervising Controller 模式。
我们把项目留在了以下状态
在这篇文章中,我将完成所需的重构步骤,并建议更多步骤以进一步加深 UI 和 BL 关注点的分离。
重构步骤
- “提取接口” – 为了获得更好的封装性和关注点分离,
CoursesPresenter
不应该直接访问CoursesView
。毕竟,CoursesPresenter
感兴趣的唯一功能是CoursesView Courses
属性。因此,我们将从CoursesView
类中提取一个接口
,如下所示:右键单击CoursesView
类 » 重构 » 提取接口,并选择Courses
属性,如图所示 - 编译解决方案并执行单元测试。
- 在
CoursesPresenter
类中,将所有CoursesView
的出现更改为ICoursesView
。 - 编译解决方案并执行单元测试。
- 上次,我们指出 Presenter 应该通过订阅 View 来处理复杂的用户事件。在引入
ICoursesView 接口
后,这很简单。在接口
中添加以下代码event Action LoadCourses; event Action SaveCourses;
- 在
CoursesView
类中实现新添加的事件public event Action LoadCourses; public event Action SaveCourses;
- 在
CoursesPresenter
类中,将Load
和Save
方法分别重命名为LoadCoursesEventHandler
和SaveCoursesEventHandler
。使用右键单击 » 重构 » 重命名工具轻松重命名。 - 在
CoursesPresenter
构造函数中连接事件,如下所示public CoursesPresenter(ICoursesView view) { this.view = view; view.LoadCourses += LoadCoursesEventHandler; view.SaveCourses += SaveCoursesEventHandler; }
- 编译解决方案并执行单元测试。
- 在
CoursesView
类中,添加通知代码private void NotifyObservers(Delegate del) { Delegate[] observers = del.GetInvocationList(); foreach (Delegate observer in observers) { try { Action action = observer as Action; if (action != null) { action.DynamicInvoke(); } } catch { // graceful degradation. } } }
- 将
CoursesView.Load
和CoursesView.Save
方法更改为分别调用NotifyObservers
private void FrmMain_Load(object sender, EventArgs e) { //... NotifyObservers(LoadCourses); //... } private void Save() { //... NotifyObservers(SaveCourses); //... }
- 编译解决方案并执行单元测试。
- 现在是时候删除
Load
和Save
方法中CoursesPresenter
类所有临时实例了。删除所有出现的地方。 - 在 Program.cs 类中,将
Application.Run(new CoursesView())
替换为以下代码static void Main() { //... CoursesView coursesView = new CoursesView(); CoursesPresenter coursesPresenter = new CoursesPresenter(coursesView); Application.Run(coursesView); }
这完成了“分离领域与表现”重构。
我们最终得到了以下结果
对于下一步可能的步骤,请考虑以下事项
- 检查 CoursesView.Designer.cs 并删除所有
TableAdapter
实例。 - 创建 DAL 并将
Save
和Load
方法进一步移动,从 Presenter 移动到 DAL。 - 使用 抽象工厂 或使用 依赖注入 创建
CoursesView
和CoursesPresenter
。