zoukankan      html  css  js  c++  java
  • FizzBuzzWhizz是算法题吗?我从设计的角度去解决的。

    今天在网上看到FizzBuzzWhizz这个代码挑战啊。觉得很有意思。开始没有看其他人的文章。写完之后,好像大家都是从算法的角度去解决问题啊。我却是一开始从设计的角度去解决问题。不知道他们出这道题到底是要考验算法呢?还是面向对象的设计呢?但是我看要求里写了要体现超赞的面向对象设计啊。而且我看了他们公司,也是一个以设计专长的公司。是要考虑算法的问题吗?

    首先,我看到这道题。现在是有三种特殊数字。分别是Fizz、Buzz、和WHizz。这就是对应三个类吧。至于当某一个数字即是第一个数的倍数又是第二个数的倍数时,就要调用Fizz类和Buzz类来处理。所以我想。某一个数字要走的流程应该是先从Fizz类处理事件,再到Buzz类处理事件,最后到Whizz类处理。是穿透的。这样的流程,类似于行为型的设计模式吧。有哪些,脑子里应该有个大概的轮廓了。可能有责任链模式、装饰者模式、状态模式等。当然这些东西不重要。重要的是思想,不能死套用模式。本来想用类似于事件机制来实现的。可是发现,这样一来,Fizz、Buzz这些类就跟事件类耦合了。这样不好。并且,我想他们要考察的不是完成他们明文写的需求上的东西吧。更要考虑的是以后那些可以预见的需求变化。比如说,我可能这个时候不要输出字符了,我要进行别的操作。又或者是我要增加一个特殊数字。变成4个。这样一来,那么写算法的同学们是不是会非常的苦恼呢?至于,我用的什么模式,我只想说,我不清楚。我做设计的时候,从来不从模式出发,我是从灵活度和扩展性出发。如果现有代码不能满足可预见的变化。那就改成可以适应变化的。所以,代码的设计,其实并不是一种设计模式就能搞定的。是设计思想的融合。

    我的思路是,将某个数字被某个特殊数字捕捉到要处理的情况。原先是直接输出字符。我想以后可能会不光是输出字符。所以,我将这部分的行为放到了外面。通过委托的方式调用。而且,考虑到这个题目本身就是输出字符,如果,我要在外部定义委托。那么对外的接口,就会变得复杂。我希望的是,对外的接口变得简单。就类似于外观模式。

    在考虑到,以后如果要增加一个特殊数字,我希望能自由的组合这些流程。所以,就有了类似于装饰着模式或者责任链模式的设计。

    /// <summary>
        /// 第二个特殊数字类
        /// </summary>
        public class Buzz : IFizzBuzzWhizz
        {
            /// <summary>
            /// 创建第二个特殊数字处理类实例
            /// </summary>
            /// <param name="specialNumber">特殊数字</param>
            /// <param name="nextFlow">下一个流程,这里指第三个特殊字处理类</param>
            /// <param name="multipleAction">当某个数字被这个类Handle的时候,要执行的事件(这里默认是如果某个数字是这个特殊数字的倍数,就在控制台输出一段字符)</param>
            public Buzz(int specialNumber, IFizzBuzzWhizz nextFlow, Action<int, bool> multipleAction)
            {
                this.SpecialNumber = specialNumber;
                this.NextFlow = nextFlow;
                this.MultipleAction = multipleAction;
            }
    
            public Buzz(int specialNumber, Action<int, bool> multipleAction)
                : this(specialNumber, new Whizz(7), multipleAction)
            {
            }
    
            public Buzz(int specialNumber)
                : this(specialNumber, new Whizz(7), (number, isHandle) => Console.Write("{0}Buzz", isHandle ? string.Empty : "
    "))
            {
            }
    
            /// <summary>
            /// 当某个数字是这个特殊数字的倍数的时候,要执行的事件
            /// </summary>
            public Action<int, bool> MultipleAction { get; set; }
    
            /// <summary>
            /// 特殊数字
            /// </summary>
            public int SpecialNumber { get; set; }
    
            /// <summary>
            /// 下一个流程,这里指第三个特殊数字处理类
            /// </summary>
            public IFizzBuzzWhizz NextFlow { get; set; }
    
            /// <summary>
            /// 处理方法
            /// </summary>
            /// <param name="number">数字</param>
            /// <param name="isHandle">是否被处理过</param>
            public void Process(int number, bool isHandle)
            {
                //如果当前的数字是这个特殊数字的倍数,就执行事件。并且标记isHandle为True,传递到下一个流程。
                if (number % this.SpecialNumber == 0)
                {
                    if (this.MultipleAction != null)
                        this.MultipleAction(number, isHandle);
                    isHandle = true;
                }
                if (this.NextFlow != null)
                    this.NextFlow.Process(number, isHandle);
            }
        }
    View Code
    /// <summary>
        /// 特殊数字第一个类
        /// </summary>
        public class Fizz : IFizzBuzzWhizz
        {
            /// <summary>
            /// 构造一个第一个特殊数字的处理类实例
            /// </summary>
            /// <param name="specialNumber">特殊数字</param>
            /// <param name="nextFlow">下一个流程,这里值第二个特殊数字处理类实例</param>
            /// <param name="containsSpecialNumberAction">当某个数字包含当前的特殊数字时,要执行的事件,这里默认是输出一段字符</param>
            /// <param name="multipleAction">当某个数字是当前特殊数字的倍数时,要执行的事件</param>
            public Fizz(int specialNumber, IFizzBuzzWhizz nextFlow, Action<int> containsSpecialNumberAction, Action<int, bool> multipleAction)
            {
                this.SpecialNumber = specialNumber;
                this.NextFlow = nextFlow;
                this.ContainsSpecialNumberAction = containsSpecialNumberAction;
                this.MultipleAction = multipleAction;
            }
    
            public Fizz(int specialNumber, Action<int> containsSpecialNumberAction, Action<int, bool> multipleAction)
                : this(specialNumber, new Buzz(5), containsSpecialNumberAction, multipleAction)
            {
            }
    
            public Fizz(int specialNumber)
                : this(specialNumber, new Buzz(5), delegate { Console.Write("
    Fizz"); }, (number, isHandle) => Console.Write("
    Fizz"))
            {
            }
    
            /// <summary>
            /// 当某个数字包含当前的特殊数字时,要执行的事件
            /// </summary>
            public Action<int> ContainsSpecialNumberAction { get; set; }
    
            /// <summary>
            /// 当某个数字是当前特殊数字的倍数时,要执行的事件
            /// </summary>
            public Action<int, bool> MultipleAction { get; set; }
    
            /// <summary>
            /// 特殊数字
            /// </summary>
            public int SpecialNumber { get; set; }
    
            /// <summary>
            /// 下一个特殊数字处理类,这个默认值第二个特殊数字处理类
            /// </summary>
            public IFizzBuzzWhizz NextFlow { get; set; }
    
            /// <summary>
            /// 处理特殊数字
            /// </summary>
            /// <param name="number">数字</param>
            /// <param name="isHandle">是否被处理</param>
            public void Process(int number, bool isHandle = false)
            {
                //如果某个数字包含当前的特殊数字,那么就执行当某个数字包含当前特殊数字的事件,并且。终止往后调用。
                if (number.ToString(CultureInfo.InvariantCulture).Contains(this.SpecialNumber.ToString(CultureInfo.InvariantCulture)))
                {
                    if (this.ContainsSpecialNumberAction != null)
                        this.ContainsSpecialNumberAction(number);
                    return;
                }
                //如果某个数字是当前特殊数字的倍数的时候,就执行是倍数时要执行的事件。并且标记ishandle为true。传递到下一个流程
                if (number % this.SpecialNumber == 0)
                {
                    if (this.MultipleAction != null)
                        this.MultipleAction(number, isHandle);
                    isHandle = true;
                }
                //调用下一个流程的方法
                if (this.NextFlow != null)
                    this.NextFlow.Process(number, isHandle);
            }
        }
    View Code
    /// <summary>
        /// 第三个特殊数字处理类
        /// </summary>
        public class Whizz : IFizzBuzzWhizz
        {
            /// <summary>
            /// 构造一个第三个特殊数字处理类
            /// </summary>
            /// <param name="specialNumber">特殊数字</param>
            /// <param name="nextFlow">下一个流程,这里默认是null,因为目前就三种情况</param>
            /// <param name="multipleAction">当某个数字是特殊数字的倍数时,所要触发的事件</param>
            /// <param name="neverHandleAction">当从来没用被任何一个特殊数字类处理过的时候要执行事件(这里就是指,这个数字既不是第一个特殊数字的倍数,也不是第二个特殊数字的倍数,更不是第三个特殊数字的倍数)</param>
            public Whizz(int specialNumber, IFizzBuzzWhizz nextFlow, Action<int, bool> multipleAction, Action<int, bool> neverHandleAction)
            {
                this.SpecialNumber = specialNumber;
                this.NextFlow = nextFlow;
                this.MultipleAction = multipleAction;
                this.NeverHandleAction = neverHandleAction;
            }
    
            public Whizz(int specialNumber, Action<int, bool> multipleAction, Action<int, bool> neverHandleAction)
                : this(specialNumber, default(IFizzBuzzWhizz), multipleAction, neverHandleAction)
            {
            }
    
            public Whizz(int specialNumber)
                : this(specialNumber, default(IFizzBuzzWhizz), (number, isHandle) => Console.Write("{0}Whizz", isHandle ? string.Empty : "
    "), (number, isHandle) => Console.Write("{0}{1}", isHandle ? string.Empty : "
    ", number))
            {
            }
    
            public Action<int, bool> MultipleAction { get; set; }
    
            public Action<int, bool> NeverHandleAction { get; set; }
    
            public int SpecialNumber { get; set; }
    
            public IFizzBuzzWhizz NextFlow { get; set; }
    
            public void Process(int number, bool isHandle)
            {
                if (number % this.SpecialNumber == 0)
                {
                    if (this.MultipleAction != null)
                        this.MultipleAction(number, isHandle);
                    isHandle = true;
                }
                if (!isHandle)
                {
                    if (this.NeverHandleAction != default(Action<int, bool>))
                        this.NeverHandleAction(number, isHandle);
                }
                if (this.NextFlow != null)
                    this.NextFlow.Process(number, isHandle);
            }
        }
    View Code
    /// <summary>
        /// 游戏控制者
        /// </summary>
        public class GameController
        {
            public string StartGame(int players, params int[] numbers)
            {
                var fizz = new Fizz(numbers[0]);
                var buzz = new Buzz(numbers[1]);
                var whizz = new Whizz(numbers[2]);
                fizz.NextFlow = buzz;
                buzz.NextFlow = whizz;
                var result = new StringBuilder();
                for (var i = 1; i <= players; i++)
                {
                    fizz.Process(i);
                }
                return result.ToString();
            }
        }
    View Code

    下面附上我的代码。欢迎大家提供不同的面向对象设计思路。

    https://github.com/freestyleSago/FizzBuzzWhizz.git

  • 相关阅读:
    《虚拟伙伴》AR增强现实应用开发总结
    捕获起英文名Edda的灵感来源,我的心愿是程序员这个行业能够男女人数平衡
    侯捷老师C++大系之C++面向对象开发:(一)不带指针的类:Complex复数类的实现过程
    【腾讯GAD暑期训练营游戏程序班】游戏中的物理系统作业说明文档
    socketAPI:一个最简单的服务器和对应的客户端C语言的实现
    C/C++实践笔记 008
    C/C++实践笔记 007
    学习java之泛型类和泛型方法
    学习java之利用泛型访问自己定义的类
    学习java之HashMap和TreeMap
  • 原文地址:https://www.cnblogs.com/Sago/p/3711778.html
Copyright © 2011-2022 走看看