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 : "\r\n"))

        {

        }



        /// <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("\r\nFizz"); }, (number, isHandle) => Console.Write("\r\nFizz"))

        {

        }



        /// <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 : "\r\n"), (number, isHandle) => Console.Write("{0}{1}", isHandle ? string.Empty : "\r\n", 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

你可能感兴趣的:(算法)