十五、 Mediator的设计
华容道自动求解程序的解题过程可以说是Layout、CircularLinkedList、AVLTree和TreeLinkedList相互协作的过程。为了降低对象间的耦合度,引入了一个中介者Mediator,负责协调它们之间的调用。我们可以在CircularLinkedList对象以及Layout对象中看到各有一个Mediator对象的引用。同时也可以看到Mediator对象持有CircularLinkedList、AVLTree和TreeLinkedList的引用。
Mediator对象首先初始化各个对象,为CircularLinkedList对象创建若干个节点以备使用,同时为TreeLinkedList与AVLTree添加根节点。代码如下:
{
for(int i = 0; i<n; i++)
_circleList.insertNode();
ChessStep c = _circleList.Initialize();
_treeList.ClearAll();
_avlTree.DestroyTree();
_treeList.insertNode(c);
_avlTree.Insert(c.layout);
_circleList.mediator = this;
}
Mediator初始化完成后,我们就可以通过调用Mediator的BeginProcess方法启动搜索过程,Stop方法停止搜索。另外通过Release方法释放所有占用的内存资源。
{
_circleList.ClearAll();
_treeList.ClearAll();
_avlTree.DestroyTree();
}
public bool BeginProcess()
{
return _circleList.BeginProcess();
}
public void Stop()
{
_circleList.Stop();
}
Mediator中的其它方法是为协调个运算对象设计的。我们可以从以下几个方面来看看Mediator是如何协调对象间的工作的:
首先,当某个Layout的CheckAvailableSteps方法被调用,并找到一个可行的布局后,Layout首先检查这个布局是否已经达到解题目的,如果没有,则调用Mediator的CheckStep方法,检查这个布局和以往布局是否有重复,如果没有重复,则将此布局以及走法添加到TreeLinkedList与AVLTree中,并通知CircularLinkedList确认分配的空间。如果布局就是最终解,则调用Layout的Finished方法,追溯棋局走法并输出结果。Layout中的代码如下:
if(l.IsFinished)
{
_gotTheAnswer = true;
_mediator.Finished(cs);
}
else
_mediator.CheckStep(cs);
这个过程可以用以下两个序列图来描述:
代码实现如下:
{
try
{
_avlTree.Insert(cStep.layout);
_circleList.ConfirmAllocation();
_treeList.insertNode(cStep);
}
catch
{
}
}
public void Finished(ChessStep cStep)
{
_circleList.Stop();
ChessStep[] s = _treeList.TraceResult(cStep);
_resultHandler.HandleResult(s);
return;
}
Mediator除了实现上述功能外,它还作为CircularLinkedList与TreeLinkedList通讯的一个中间渠道。在前面的文章中曾经提到过,要确保TreeLinkedList中的current指针与CircularLinkedList中的current指针同步移动;同时,Layout在求解的过程中也需要从CircularLinkedList中分配一些可用的Layout来使用。所有这些都是通过Mediator来协调的。
{
return _circleList.AllocateLayout();
}
public void MoveCurrentToNext()
{
_treeList.MoveCurrentToNext();
}
Mediator的引入降低了各对象间的耦合度,增强了系统的灵活性。
在后面的内容中,我将介绍Sample中的代码实现以及性能方面的测试和讨论。