zoukankan      html  css  js  c++  java
  • 从动物叫三声,谈谈设计模式

    从动物叫三声,谈谈设计模式

    作者:肖波

             今天在博问中看到一个动物叫三声的设计模式讨论,觉得很有意思,抽空实现了一下,觉得有必要写下来,和大家一起探讨探讨。

             原始需求:http://space.cnblogs.com/question/2360/ 我把原文转贴如下:

             我有一个动物类,它只有一个“叫三声”的方法,然后猫类与狗类都从它继承而来。现在我想猫应该“喵喵喵”叫,狗应该“汪汪汪”叫,我是用如下代码实现,但,有没有更好的方法,或是一些能用得上设计模式的方法(我是为设计模式而设计模式)。

             从这篇博问的回复中,很多意见是使用抽象方法描述 基类 animal 中的shout 方法,不同动物对这个方法进行重载,以达到用不同方式叫的目的。

             我谈谈我的设计:

             首先我们看到这个需求中有两个重要概念:

              一个是叫,还有一个是叫声。

             Shout(叫)是一个动作,不同动物有不同的叫声,但只要是动物就会叫(不会叫的动物不在这里讨论,原始需求中并没有要求),另外原始需求中要求叫就是

    叫三声,所以怎么叫也规定了。显然把Shout这个方法应该放到基类中。

             Sound(叫声)是一个属性,不同动物有不同的叫声,同一个动物不同情况下也可能会发出不同的叫声。叫声不是动作,因为不张口,有声音也出不来。所以这里应该把叫声这个概念单独提取出来作为一个属性。

             下面看我的代码:

            

        /// <summary>
        
    /// 叫声属性
        
    /// </summary>
        [AttributeUsage(AttributeTargets.All)]
        
    class SoundsAttribute : Attribute
        {
            
    string _Sounds;

            
    /// <summary>
            
    /// 叫声
            
    /// </summary>
            public string Sounds
            {
                
    get
                {
                    
    return _Sounds;
                }
            }

            
    public SoundsAttribute(string sounds)
            {
                _Sounds 
    = sounds;
            }
        }

            上面代码是叫声属性,采用属性(Attribute)来描述,而不是特性(Property),可以时程序看起来更优雅。

        /// <summary>
        
    /// 动物类
        
    /// </summary>
        abstract class Animal
        {
            
    private SoundsAttribute m_AnimalSounds;

            
    /// <summary>
            
    /// 获取动物的一般叫声
            
    /// </summary>
            public Animal()
            {
                
    //获取当前对象的类型
                Type myType = this.GetType();

                
    //获取一般叫声
                foreach (Attribute attr in myType.GetCustomAttributes(true))
                {
                    
    if (attr is SoundsAttribute)
                    {
                        m_AnimalSounds 
    = attr as SoundsAttribute;
                    }
                }
            }

            
    /// <summary>
            
    /// 叫
            
    /// </summary>
            public void Shout()
            {
                SoundsAttribute animalSounds 
    = m_AnimalSounds;

                
    //叫三声
                if (animalSounds != null)
                {
                    
    for (int i = 0; i < 3; i++)
                    {
                        Console.Write(animalSounds.Sounds);
                    }
                }

                Console.WriteLine();
            }
        }

     上面代码是动物类,由于动物本身是一个抽象概念,所以在设计时最好和自然规律吻合,将其设计为抽象类应该是不错的选择。

        [Sounds("")]
        
    class Cat : Animal
        {
        }

        [Sounds(
    "")]
        
    class Dog : Animal
        {
        }

      猫猫狗狗

        class Program
        {
            
    static void Main(string[] args)
            {
                
    //
                Cat cat = new Cat();
                
    //猫叫三声
                cat.Shout();

                
    //
                Dog dog = new Dog();
                
    //狗叫三声
                dog.Shout();

            }
        }

     猫叫三声,够叫三声

     结果:

     喵喵喵

     汪汪汪

    写到这边,基本的设计思路和程序实现已经完成。

    下面我们来扩展一下需求,看看当前的设计架构是否可以很好的适应需求的变化。

    第一,我们希望有个别的动物,叫的时候不是叫三声,而是采取一些特殊的叫法。要做到这点很简单,我们只要将

    Animal类中的Shout 方法改为virtual(虚拟)方法,那么派生出来的动物如果不想采用这种方法叫,就可以覆盖这个

    虚拟方法,实现其特殊的叫法。

    第二,狗在Frenzy(狂怒)时,往往不是发出"汪汪"的叫声,可能是那种低沉的"吼吼"的叫声,现在我们要为狗的狂怒设计一个

    方法。由于只是发出的声音不同,我们希望依然使用Animal 类中的Shout方法来发出叫声,但声明Frenzy这个方法采用

    "吼"这种叫声。


    下面看代码,我们将Shout 方法修改如下:

            /// <summary>
            
    /// 叫
            
    /// </summary>
            virtual public void Shout()
            {
                SoundsAttribute animalSounds 
    = null;

                Type myType 
    = this.GetType();

                
    //获取上一个调用函数
                System.Diagnostics.StackFrame stackFrame = new System.Diagnostics.StackFrame(1);
                MethodBase methodBase 
    = stackFrame.GetMethod();

                
    //获取特殊叫声
                foreach (Attribute attr in methodBase.GetCustomAttributes(true))
                {
                    
    if (attr is SoundsAttribute)
                    {
                        animalSounds 
    = attr as SoundsAttribute;
                    }
                }

                
    //如果没有特殊叫声,用一般叫声叫
                animalSounds = animalSounds == null ? m_AnimalSounds : animalSounds;

                
    //叫三声
                if (animalSounds != null)
                {
                    
    for (int i = 0; i < 3; i++)
                    {
                        Console.Write(animalSounds.Sounds);
                    }
                }

                Console.WriteLine();
            }
        }

     我们再为狗这个类添加一个Frenzy(狂怒)方法

        [Sounds("")]
        
    class Dog : Animal
        {
            
    /// <summary>
            
    /// 狗狂怒
            
    /// </summary>
            [Sounds("")]
            
    public void Frenzy()
            {
                Shout();
            }
        }

     狗要叫了...... 好怕....

                //
                Dog dog = new Dog();
                
    //狗叫三声
                dog.Shout();
                
    //狗狂叫三声
                dog.Frenzy();

     结果:

    汪汪汪

    吼吼吼

    下面给出全部完整的代码

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Reflection;

    namespace TestCosole
    {
        
    /// <summary>
        
    /// 叫声属性
        
    /// </summary>
        [AttributeUsage(AttributeTargets.All)]
        
    class SoundsAttribute : Attribute
        {
            
    string _Sounds;

            
    /// <summary>
            
    /// 叫声
            
    /// </summary>
            public string Sounds
            {
                
    get
                {
                    
    return _Sounds;
                }
            }

            
    public SoundsAttribute(string sounds)
            {
                _Sounds 
    = sounds;
            }
        }


        
    /// <summary>
        
    /// 动物类
        
    /// </summary>
        abstract class Animal
        {
            
    private SoundsAttribute m_AnimalSounds;

            
    /// <summary>
            
    /// 获取动物的一般叫声
            
    /// </summary>
            public Animal()
            {
                
    //获取当前对象的类型
                Type myType = this.GetType();

                
    //获取一般叫声
                foreach (Attribute attr in myType.GetCustomAttributes(true))
                {
                    
    if (attr is SoundsAttribute)
                    {
                        m_AnimalSounds 
    = attr as SoundsAttribute;
                    }
                }
            }

            
    /// <summary>
            
    /// 叫
            
    /// </summary>
            virtual public void Shout()
            {
                SoundsAttribute animalSounds 
    = null;

                Type myType 
    = this.GetType();

                
    //获取上一个调用函数
                System.Diagnostics.StackFrame stackFrame = new System.Diagnostics.StackFrame(1);
                MethodBase methodBase 
    = stackFrame.GetMethod();

                
    //获取特殊叫声
                foreach (Attribute attr in methodBase.GetCustomAttributes(true))
                {
                    
    if (attr is SoundsAttribute)
                    {
                        animalSounds 
    = attr as SoundsAttribute;
                    }
                }

                
    //如果没有特殊叫声,用一般叫声叫
                animalSounds = animalSounds == null ? m_AnimalSounds : animalSounds;

                
    //叫三声
                if (animalSounds != null)
                {
                    
    for (int i = 0; i < 3; i++)
                    {
                        Console.Write(animalSounds.Sounds);
                    }
                }

                Console.WriteLine();
            }
        }

        [Sounds(
    "")]
        
    class Cat : Animal
        {
        }

        [Sounds(
    "")]
        
    class Dog : Animal
        {
            
    /// <summary>
            
    /// 狗狂怒
            
    /// </summary>
            [Sounds("")]
            
    public void Frenzy()
            {
                Shout();
            }
        }

        
    class Program
        {
            
    static void Main(string[] args)
            {
                
    //
                Cat cat = new Cat();
                
    //猫叫三声
                cat.Shout();

                
    //
                Dog dog = new Dog();
                
    //狗叫三声
                dog.Shout();
                
    //狗狂叫三声
                dog.Frenzy();
            }
        }
    }

  • 相关阅读:
    [哈希][倍增] Jzoj P5856 01串
    [exgcd] Jzoj P5855 吃蛋糕
    [折半搜索][分治][二分] Jzoj P5851 f
    [lca][主席树] Jzoj P5850 e
    [二分][树状数组] Jzoj P5849 d
    [容斥] Jzoj P5843 b
    [前缀和][枚举] Jzoj P5842 a
    [平衡规划][模拟][前缀和] Jzoj P4724 斐波那契
    [spfa] Jzoj P4722 跳楼机
    [模拟] Jzoj P2499 东风谷早苗
  • 原文地址:https://www.cnblogs.com/eaglet/p/1268392.html
Copyright © 2011-2022 走看看