65.9K
CodeProject 正在变化。 阅读更多。
Home

分离域与表示 - 第三部分

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.20/5 (7投票s)

2009 年 7 月 17 日

CDDL

2分钟阅读

viewsIcon

28949

关于“分离域与表示”系列文章的第三篇。

来自 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 类中,将 LoadSave 方法分别重命名为 LoadCoursesEventHandlerSaveCoursesEventHandler。使用右键单击 » 重构 » 重命名工具轻松重命名。
  • 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.LoadCoursesView.Save 方法更改为分别调用 NotifyObservers
    private void FrmMain_Load(object sender, EventArgs e)
    {
        //...
        NotifyObservers(LoadCourses);
        //...
    }
    private void Save()
    {
        //...
        NotifyObservers(SaveCourses);
        //...
    }
  • 编译解决方案并执行单元测试。
  • 现在是时候删除 LoadSave 方法中 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 并将 SaveLoad 方法进一步移动,从 Presenter 移动到 DAL。
  • 使用 抽象工厂 或使用 依赖注入 创建 CoursesViewCoursesPresenter

© . All rights reserved.