当前位置:编程学习 > 网站相关 >>

《模式——工程化实现及扩展》(设计模式C# 版)《中介者模式》——“自我检验 参考答案

  cnblogs.com/callwangxiang/
 

 

 

 

 MarvellousWorks公司有A、B、C三个部门负责文件的拟稿、审批和备案,现有的流程如下:

 1.         A部门拟稿后将文件报B部门审核

2.         B部门对于文件审核后,确认文件体例没有缺项后就通知C部门发布

3.         如果B部门发现文件体例有缺项时,将文件返回给A部门重新修改

4.         C部门在接到B部门传来的文件时,先再发布,然后对其归档

 

不过,MarvellousWorks的管理层为了加强部门间文件流转的管理,正在酝酿修改工作流程:

1、 增加D部门专门负责归档,C部门将归档职责划入D部门后只负责发布文件

2、 C部门发布文件后也须先在D部门归档

3、 A、B部门间所有往复流转的中间文件也都报给D部门归档

 

请采用本章介绍的中介者模式及其扩展处理,将文件的流转调度过程从A、B、C、D各对象的职责中独立出来,并用单元测试验证不同的流转过程。

 

 

文件对象的定义
 

class Document
{
    #region essential fields
    public string Subject { get; set; }
    public string Body { get; set; }
    #endregion

    #region optional fields
    public string Comment { get; set; }
    #endregion

    public override string ToString()
    {
        return string.Format(" [{0}] ------------------ {1} ({2}) ", Subject, Body, Comment);
    }
}
 

 

参考答案


 

分析第一步

上述A、B、C、D部门间的协作关系比较复杂,而且预期很快会变化,但协作的中间内容很简单——都是文件,所以采用事件方式,由.NET Framework自己的事件机制作为中介者相对很简单,而且类型间的依赖关系全都推给.NET Framework,为以后扩展更多参与方的协作关系提供便利。


 

 据此,我们定义A、B、C、D时全部采用事件作为提供给外中介者协调响应关系的入口。

 

增加如下类型

class DocumentEventArgs : EventArgs
{
    Document document;
    public DocumentEventArgs(Document document)
    {
        this.document = document;
    }
    public Document Document{get{ return document;}}
}

abstract class Department
{
    protected Document document = new Document();
    public Document Document
    {
        get{ return document;}
        protected set{ document = value;}
    }
}
 

 

分析第二步

 如果直接通过事件重载操作符 +=和-=建立各Colleague的响应关系,需要重复编写代码,而且不能在系统上线后将这个工作交给管理员维护。

因此,考虑参考前面的Builder模式,增加一个基于配置动态维护维护事件响应关系的对象。


 

 


实现和单元测试验证
 

 

1、验证“分析第一步”的设想

/// <summary>
/// 测试手工定义事件中介者的交互关系
/// </summary>
[TestMethod]
public void TestManualDefineEventMediatorInSucceedBranch()
{
    //  用事件配置松散的响应关系
    a1.WriteDocumentFinishedHandler += b1.OnReceiveFileToReview;
    b1.ReviewDocumentFailedHandler += a1.OnReviewFailed;
    b1.ReviewDocumentSucceedHandler += c1.OnReceiveFileToPublish;
    b1.ReviewDocumentSucceedHandler += c1.OnReceiveFileToArchive;

    //  成功的路径
    a1.Write("a", "b", "c");

    //  验证修订后的内容曾经流转给了B
    Assert.AreEqual<string>("a", b1.Document.Subject);
    Assert.AreEqual<string>("b", b1.Document.Body);
    Assert.AreEqual<string>("c", b1.Document.Comment);

    //  验证修订后的内容也曾经流转给了C
    Assert.AreEqual<string>("a", c1.Document.Subject);
    Assert.AreEqual<string>("b", c1.Document.Body);
    Assert.AreEqual<string>("c", c1.Document.Comment);
}
Output窗口

------ Test started: Assembly: Mediator.Tests.dll ------

A begin write
A write finished

[a]
------------------
b
(c)

B received doc from A to review
B begin review
B review succeed
C received doc to publish from B
C published
C received doc to archive from B
C archived

1 passed, 0 failed, 0 skipped, took 0.50 seconds (MSTest 10.0).
 

 

/// <summary>
/// 测试手工定义事件中介者的交互关系
/// </summary>
[TestMethod]
public void TestManualDefineEventMediatorInFailedBranch()
{
    //  用事件配置松散的响应关系
    a1.WriteDocumentFinishedHandler += b1.OnReceiveFileToReview;
    b1.ReviewDocumentFailedHandler += a1.OnReviewFailed;
    b1.ReviewDocumentSucceedHandler += c1.OnReceiveFileToPublish;
    b1.ReviewDocumentSucceedHandler += c1.OnReceiveFileToArchive;

    //  失败的路径
    a1.Write("a", "", "");

    //  验证确实文档曾经流转给了B
    Assert.AreEqual<string>("a", b1.Document.Subject);
    Assert.AreEqual<string>("", b1.Document.Body);
    Assert.AreEqual<string>("", b1.Document.Comment);

    //  验证文档并没有流转给C
    Assert.IsNull(c1.Document.Subject);
    Assert.IsNull(c1.Document.Body);
    Assert.IsNull(c1.Document.Comment);

    //  修正错误的内容,重新执行流程
    a1.Write("a", "b", "c");

    //  验证修订后的内容曾经流转给了B
    Assert.AreEqual<string>("a", b1.Document.Subject);
    Assert.AreEqual<string>("b", b1.Document.Body);
    Assert.AreEqual<string>("c", b1.Document.Comment);

    //  验证修订后的内容也曾经流转给了C
    Assert.AreEqual<string>("a", c1.Document.Subject);
    Assert.AreEqual<string>("b", c1.Document.Body);
    Assert.AreEqual<string>("c", c1.Document.Comment);
}
 

 

Output窗口
 

------ Test started: Assembly: Mediator.Tests.dll ------

A begin write
A write finished

[a]
------------------

()

B received doc from A to review
B begin review
B review failed
A received doc review failed from B
A begin write
A write finished

[a]
------------------
b
(c)

B received doc from A to review
B begin review
B review succeed
C received doc to publish from B
C published
C received doc to archive from B
C archived

1 passed, 0 failed, 0 skipped, took 3.64 seconds (MSTest 10.0).
 

 

2、验证“分析第二部” 的设想


 

 定义管理基于事件的中介关系Builder

class EventMediatorBuilder
{
    class ConfigItem
    {
        public Type SourceType { get; set; }
        public Type TargetType { get; set; }
  

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,