面向对象分析设计学习与探索(五):分析(Analysis)

    在开发的过程中,我们所写的程序如同在真空中一样,相对理想的环境,相对较好的机器。然而一旦软件部署到客户端,软件就在现实世界中工作。此时,很多性能和并发的问题就产生了。

    让软件在真实的世界中正常工作的关键是分析:在发布你的程序前,指出潜在的问题,然后解决他们。分析帮助你确保你的系统在现实环境中工作。

    分析的第一步就是:指出潜在的问题:

    回到上一章的故事,还记得那个改进后的Dog Door。现在有了一个新的问题:邻居家的狗叫的时候,这个门也会自动打开。

OOAD4_1

   现在问题发现了,根据问题要重新修改用例。接收到声音信号后,BarkRecognizer要识别是否是这家人的小狗叫。修改后用例如下:(黑色粗体为修改的部分)

OOAD4_2

    从用例中我们可以看出,现在声音识别器在获得音频信号后,要进行比对,以确认这个声音是否为此家人的小狗。这样,我们就要保存一个小狗的声音用来比对。所以我们需要一个新的用例来保存狗的叫声。

    OOAD4_3

    用例更新后,程序需要做相应的修改,但是有一个问题出现:如何更改。实际上程序有很多实现方式。如何选择?

    有人认为:简单是最好的。既然需要一个对象存储小狗的叫声,当需要的时候进行比对,那我们可以用一个String对象来存储。只需要在Dog Door 对象中进行修改。代码修改如下:

 

public class DogDoor

    
private String _allowedBark; 

    
public String AllowedBark 
    

        
get return _allowedBark; } 
        
set { _allowedBark = value; } 
     }
 

     
// 
}
 

    相应的BarkRecognizer()中也需要修改:

 

    public class BarkRecognizer 
    

        DogDoor door 
= new DogDoor(); 

        
public void recognizer(String Bark)
        

              
if (door.AllowedBark == Bark) 
              

                 door.Open(); 
               }
 
         }
 

         
// 
      }
 


    也有人更忠实于面向对象。在这种情况下,编写一个Bark类型,并赋予相应的比较方法。

添加Bark类型:

 

public class Bark 

    
private String _sound; 

    
public Bark(String sound) 
    

        _sound 
= sound; 
    }
 

    
public String Sound 
    

        
get return _sound; } 
    }
 

    
public Boolean Equal(Bark bark) 
    

        Boolean flag 
= false
        
if (bark._sound == _sound) 
        

            flag 
= true
        }
 
        
return flag; 
    }
 
}
 


当然,Dog Door类型也需要修改,代码如下:

 

public class DogDoor 

    
private Bark _allowedBark; 
    
public Bark AllowedBark 
    

        
get return _allowedBark; } 
        
set { _allowedBark = value; } 
    }
 

    
// 
}
 


BarkRecognizer类型中的修改如下:

 

public class BarkRecognizer 

    DogDoor door 
= new DogDoor(); 
    
public void recognizer(Bark Bark) 
    

        
if (door.AllowedBark.Equal(Bark)) 
        

            door.Open(); 
        }
 
    }
 

    
// 
}
 


    那么哪一种方式更好呢?在这里要提到一个问题:解耦合。也就是说,你的对象对于其他的对象是独立的,或者说一个对象的变化不会导致其他对象的变化。书中写道:Delegation helps our applications stay loosely couples。意思是说:Delegation帮助我们的程序保持松耦合,对于Delegation的翻译,我一直觉得是代理。但在这里我感觉是封装的意思,不知我的理解是否正确。回到刚才两个方法的讨论:如果对于小狗的叫声存储的是声音文件,比如说WAV,对于第二种方式我们只需要修改Bark类型中的Equal方法就可以,BarkRecognizer类型中不需要修改。Delegation shields your object from implementation changes to other objects in your softwave

    但是现在又出现一个很实际的问题:小狗的叫声可能有很多种,无论哪一种,我们应该让门打开。那么在DogDoor类型中的AllowedBark应该是一组Bark对象,换句话说:AllowedBark应该是List<Bark>类型。

    说到这里,一个疑惑出现了,如何确定一个程序中的类型?注意用例中的名词。用例中的名词往往是你系统中所需要实现的类型。那么现在把用例中的名词圈出来。

OOAD4_5

    不难看出,很多名词是系统中需要的类型。当然也有些名词是不需要注意的,如;button owner outside inside

    书中提到一个词:textual analysis 文本分析。

    Looking at nouns and verbs in your use case to figure out classes and methods is called textual analysis.

    回到用例中,注意用例中的第三步:3.If it’s the owner’s dog barking. The bark recognizer sends a request to the door open. Owner’s dog是一个名字,但是我们不需要为dog创建一个类型,因为他是发起者,在系统之外。对于Bark,不要只把关注点放到Bark上,还要注意是the owner’s dog。

现在不难看出用例的重要性。尤其是对文本分析的重要性。OOAD4_6

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    对于用例中的动词,实际上是系统重要实现的方法。

OOAD4_7

    完成分析后,明确了系统中需要的类型和方法,我们可以很简单的画出系统的类图。类图中可以描述类型之间的依赖关系。

OOAD4_8

    分析得差不多了,类图也画出来了。虽然类图可以很清楚的表现出类型之间的关系,但是不能告诉我们代码是如何实现的。下面我们来看看代码的实现:

    首先编写Bark类型

 

    public class Bark
    
{
        
private String _sound; 

        
public Bark(String sound)
        
{
            _sound 
= sound;
        }
 

        
public String Sound
        
{
            
get return _sound; }
        }
 

        
public Boolean Equal(Bark bark)
        
{
            Boolean flag 
= false

            
if (bark._sound == _sound)
            
{
                flag 
= true;
            }

            
return flag;
        }

    }
 

    
    在DogDoor类型中加入如下代码:

        

        private List<Bark> _allowedbarks; 

        
public List<Bark> AllowedBarks
        
{
            
get return _allowedbarks; }
            
set { _allowedbarks = value; }
        }
 


    修改BarkRecognizer中的recognize方法,代码如下:         

        public void recoginze(Bark bark)
        
{
            Console.WriteLine(
" BarkRecognizer heard a '" + bark.Sound + "'");
            
foreach (Bark allowbark in _door.AllowedBarks)
            
{
                
if (bark.Equal(allowbark))
                
{
                    _door.Open();
                    
break;
                }

                
else
                
{
                    
continue;
                }

            }

        }
 


    最后修改测试代码并查看结果:

       

        static void Main(string[] args)
        
{
            DogDoor door 
= new DogDoor();
            door.AllowedBarks.Add(
new Bark("Woof"));
            door.AllowedBarks.Add(
new Bark("Yip"));
            BarkRecognizer recognizer 
= new BarkRecognizer(door);
            Remote remote 
= new Remote(door);
            Console.WriteLine(
"The dog is barking, he wanna "); 

            Bark bark1 
= new Bark("Woof");
            recognizer.recoginze(bark1);
            Console.WriteLine(
"The dog is outside and ");
            Thread.Sleep(
10000); 

            Bark bark2 
= new Bark("Yip");
            Console.WriteLine(
"The dog is barking, he wanna inside");            
            recognizer.recoginze(bark2);
            Console.WriteLine(
"The dog is inside");
            Thread.Sleep(
10000); 

            Console.WriteLine(
"Another dog is barking");
            Bark bark3 
= new Bark("Hooh");
            recognizer.recoginze(bark3);
            Console.Read();
        }
 


    输出结果为:

OOAD4_9

posted @ 2007-09-26 17:10  KiddLee  Views(3308)  Comments(12Edit  收藏  举报