享受代码,享受人生

SOA is an integration solution. SOA is message oriented first.
The Key character of SOA is loosely coupled. SOA is enriched
by creating composite apps.
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

从一个画图程序谈起---重构(2)

Posted on 2005-01-29 19:18  idior  阅读(1377)  评论(4编辑  收藏

上文中我给出了画图程序的一种最普通也最常见的做法。就是把处理逻辑全放在系统的事件处理函数中,这种方法有以下几个缺点:

1.        逻辑性不强,写到后面自己都绕不过弯来。

2.        一个函数做了太多的事情,复杂的处理逻辑全放在系统的事件处理函数中。

3.        有条件判断,在目前这个简单的应用中还显不出它的可怕,不过它的坏处想想也知道多严重。你可以参考吕震宇的条件外置

那么,如何才能采取一个有效的方案解决这个问题呢?一步一步来,让我们从重构开始。
 

private void Form1_MouseDown(object sender, MouseEventArgs e)
        
{
            
if (bDrawLine && bFirstDown)
            
{
                
this.Cursor = Cursors.Cross;
                Line newLine 
= new Line();
                newLine.StartPoint 
= new Point(e.X, e.Y);
                drawingLine 
= newLine;
                bFirstDown 
= false;
            }

            
else if (bDrawLine == true && bFirstDown == false)
            
{
               if (drawingLine != null)
            
{
                drawingLine.EndPoint 
= new Point(e.X, e.Y);
                AddLine(drawingLine);
                }

            
this.Cursor = Cursors.Arrow; 
             }
        }


这么多的逻辑,看的太乱了。先使用Extract Method,把条理弄弄清楚。

private void Form1_MouseDown(object sender, MouseEventArgs e)
        
{
            
if (bDrawLine && bFirstDown)
            
{
                RecordFirstPt(e);
                bFirstDown 
= false;
            }

            
else if (bDrawLine == true && bFirstDown == false)
            
{
                RecordSecondPt(e);
                bFirstDown 
= true;
            }

        }


        
private void RecordSecondPt(MouseEventArgs e)
        
{
            
if (drawingLine != null)
            
{
                drawingLine.EndPoint 
= new Point(e.X, e.Y);
                AddLine(drawingLine);
            }

            
this.Cursor = Cursors.Arrow;
        }


        
private void RecordFirstPt(MouseEventArgs e)
        
{
            
this.Cursor = Cursors.Cross;    
            Line newLine 
= new Line();
            newLine.StartPoint 
= new Point(e.X, e.Y);    
            drawingLine 
= newLine;
        }


 

这样主逻辑清楚了许多。

第一次按下鼠标,记录第一个点,然后设为第二种状态,下次再点击的时候,记录第二个点,此时完成一条线段,再回到第一种状态。

两个状态,不错再重构一下。让状态的意思表现出来。


private void Form1_MouseDown(object sender, MouseEventArgs e)
        
{
            
if (IsGetFirstPointState())
            
{
                RecordFirstPt(e);
                SetToGetSecondPtState();
            }

            
else if (IsGetSecondPointState())
            
{
                RecordSecondPt(e);
                SetToGetFirstPtState();
            }

        }


        
private bool IsGetSecondPointState()
        
{
            
return bDrawLine == true && bFirstDown == false;
        }


        
private void SetToGetFirstPtState()
        
{
            bFirstDown 
= true;
        }


        
private void SetToGetSecondPtState()
        
{
            bFirstDown 
= false;
        }


        
private bool IsGetFirstPointState()
        
{
            
return bDrawLine && bFirstDown;
        }


 这样状态的意思就出来了,很好现在的逻辑清晰了许多,再看看下面这个鼠标移动的函数

private void Form1_MouseMove(object sender, MouseEventArgs e)
        
{
            
if (bFirstDown == false)
            
{
                
if (drawingLine != null)
                
{
                    Point mousePoint 
= new Point(e.X, e.Y);
                    DrawLine(drawingLine.StartPoint, mousePoint);
                }

            }

        }


把它也改一下:(具体省略同上)


private void Form1_MouseMove(object sender, MouseEventArgs e)
        
{
            
if (IsGetSecondPointState())
            
{
                DragLine(e);
            }

        }


通过上面的重构,你对这个画线的过程是否更加清晰了?现在剩下的缺点就在于那个条件判断了。如何把条件判断消除?多态!详见下篇随笔