zoukankan      html  css  js  c++  java
  • Head.First.ObjectOriented.Design.and.Analysis《深入浅出面向对象的分析与设计》读书笔记(四)

     用真实世界检验你的软件-分析

     引用

         

          是时候毕业了,时候去真实世界检验自己的软件了。

         

          上个版本的狗门很是成功,卖的很疯狂。但是越是卖的还要,抱怨就会越多。下面就是一个用户的意见。

          “我非常喜欢你的系统,那个语音识别器。但是在我安装了之后,每次邻居家的狗叫的话,门也会自动打开。但是这不是我想要的效果。”

     正文

         

          你的软件有了一个上下文。到目前为止,我们是在一个真空,没有结合软件运行环境的情况下开发软件。换句话说,我们把软件想象为:运行在完美的世界,在我们预期的情况下运行。每个人都很轻松,周围没有很多条狗。

          但是我们的软件终究要运行在真实的世界,而不是一个完美的世界。在真实的世界中,可能会运行错误。周围也会有很多的狗,猫之类的动物。

          使得你的软件在真实世界不被搞糟的关键在于分析:在你把软件放到真实世界之前,找出潜在的问题,并且解决这些问题。

          1、确定(识别)问题

          第一步是找到潜在的问题。我们已经知道,就是邻居家有很多只狗。

          使用遥控器没有问题,因为是人工干预。人是可以识别自己家的狗叫的。但是语音识别器好像就差了点,它一听到狗叫就会打开门。意味着,任何一只狗叫都可以打开门。

          2、设计一个解决方案

          使我们的use case出了问题,在识别器听到狗叫之后没有识别是否是自己家的狗,就打开了门。应该在听到声音之后,需要if判断一下,然后再打开门。

          还需要识别器有存储主人家的狗叫声,才可以在收到狗叫之后进行比较。这时候,你就会发现,需要添加一个use case,就是存储狗叫。用例比较简单,就是:

          1)主人家的狗叫

          2)识别器存储主人家的狗叫声

          用例增加之后,就需要我们修改代码。修改的方式有很多种,先看第一种:

          在DogDoor中添加一个string类型的字段,用来存储叫声;添加一个方法来设置叫声;添加方法来获取叫声。

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace BeautyCode.Common.ConApp.Head.First.OO.Design
    {
        
    public class DogDoor
        {
            
    private bool _open;
            
    private string _allowBark;
            
    public void SetAllowBark(string bark)
            {
                _allowBark 
    = bark;
            }
            
    public string GetAllowBark()
            {
                
    return _allowBark;
            }
            
    public DogDoor()
            {
                _open 
    = false;
            }
            
    public void Open()
            {
                Console.WriteLine(
    "the dog door opens");
                
    this._open = true;

                System.Threading.Thread.Sleep(
    5000);
                Close();
            }
            
    public void Close()
            {
                Console.WriteLine(
    "the dog door closes");
                
    this._open = false;
            }
            
    public bool IsOpen()
            {
                
    return _open;
            }
        }
    }

          另外一种做法就是比较面向对象的程序员写的,新建一个类,定义叫声类

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace BeautyCode.Common.ConApp.Head.First.OO.Design
    {
        
    public class Bark
        {
            
    private string _sound;
            
    public Bark(string sound)
            {
                _sound 
    = sound;
            }
            
    public string GetSound()
            {
                
    return _sound;
            }
            
    public override bool Equals(object obj)
            {
                
    if (obj is Bark)
                {
                    Bark bark 
    = obj as Bark;
                    
    if (bark._sound.Equals(this._sound))
                        
    return true;
                    
    else
                        
    return false;
                }
                
    return false;
            }
        }
    }

          DogDoor类中的叫声字段的类型则变成了新建的Bark类

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace BeautyCode.Common.ConApp.Head.First.OO.Design
    {
         
    public class DogDoor2
        {
            
    private bool _open;
            
    private Bark _allowBark;
            
    public void SetAllowBark(Bark bark)
            {
                _allowBark 
    = bark;
            }
            
    public Bark GetAllowBark()
            {
                
    return _allowBark;
            }
            
    public DogDoor2()
            {
                _open 
    = false;
            }
            
    public void Open()
            {
                Console.WriteLine(
    "the dog door opens");
                
    this._open = true;

                System.Threading.Thread.Sleep(
    5000);
                Close();
            }
            
    public void Close()
            {
                Console.WriteLine(
    "the dog door closes");
                
    this._open = false;
            }
            
    public bool IsOpen()
            {
                
    return _open;
            }
        }
    }

          相应的识别器类中的代码就应该修改为

          识别器1

    代码
      public void Recognize(string bark)
            {
                Console.WriteLine(
    "Bark Recognizer: heard a "+bark );
                
    if (_door.GetAllowBark().Equals(bark))

                    _door.Open();
                
    else
                    Console.WriteLine(
    "this dog is not allow");
            }

          识别器2

    代码
     public void Recognize(Bark  bark)
            {
                Console.WriteLine(
    "Bark Recognizer: heard a " + bark);
                
    if (_door2.GetAllowBark().Equals(bark))

                    _door.Open();
                
    else
                    Console.WriteLine(
    "this dog is not allow");
            }

          识别器2明显好于识别器1,因为在2中将声音比较的任务委托给了bark类来处理,识别器本身不处理,只是根据处理的结果来做出决定。这样就松散了耦合,解耦了识别器类和叫声类。因为其他叫声也很容可以添加进来,否则每一种叫声都必须配备专用的识别器了。

          在分析的时候,需要注意需求或者是用例中的名词和动词。名称经常会需要转换成类,或者是类的一个属性。动词则经常会是一个方法。

          继续上面的分析。

          狗一般不是叫一声,有可能要叫很多声,只要一个声音匹配成功,就应该打开门。识别器需要存储多个狗叫声。

         

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace BeautyCode.Common.ConApp.Head.First.OO.Design
    {
        
    public class DogDoor3
        {
            
    private bool _open;
            
    private List<Bark> _allowBark;
            
    public void SetAllowBark(Bark bark)
            {
                _allowBark.Add( bark);
            }
            
    public List<Bark> GetAllowBark()
            {
                
    return _allowBark;
            }
            
    public DogDoor3()
            {
                _open 
    = false;
            }
            
    public void Open()
            {
                Console.WriteLine(
    "the dog door opens");
                
    this._open = true;

                System.Threading.Thread.Sleep(
    5000);
                Close();
            }
            
    public void Close()
            {
                Console.WriteLine(
    "the dog door closes");
                
    this._open = false;
            }
            
    public bool IsOpen()
            {
                
    return _open;
            }
        }
    }

           这时候识别器就需要修改一下了

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace BeautyCode.Common.ConApp.Head.First.OO.Design
    {
        
    public class BarkRecognizer
        {

            
    private DogDoor3 _door3;
            
    public BarkRecognizer(DogDoor3 door)
            {
                _door3 
    = door;
            }
            

            
    public void Recognize3(Bark bark)
            {
                Console.WriteLine(
    "Bark Recognizer: heard a " + bark);
                
    foreach (Bark b in _door3.GetAllowBark())
                {
                    
    if (b.Equals(bark))
                    {
                        _door.Open();
                        
    return;
                    }

                }

                Console.WriteLine(
    "this dog is not allow");
            }
        }
    }

         

         

      结论

          要注意requirements和use case中的名词,它们通常就是一个类或者是类中的一个属性;其中的动词通常会是一个类的方法。

    【Blog】http://virusswb.cnblogs.com/

    【MSN】jorden008@hotmail.com

    【说明】转载请标明出处,谢谢

  • 相关阅读:
    通过HttpListener实现简单的Http服务
    WCF心跳判断服务端及客户端是否掉线并实现重连接
    NHibernate初学六之关联多对多关系
    NHibernate初学五之关联一对多关系
    EXTJS 4.2 资料 跨域的问题
    EXTJS 4.2 资料 控件之Grid 那些事
    EXTJS 3.0 资料 控件之 GridPanel属性与方法大全
    EXTJS 3.0 资料 控件之 Toolbar 两行的用法
    EXTJS 3.0 资料 控件之 combo 用法
    EXTJS 4.2 资料 控件之 Store 用法
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/1784437.html
Copyright © 2011-2022 走看看