【U3D日记-2016年9月2日】设计模式解决工作问题的一个实例

来源:互联网 发布:乐知英语的公司在哪 编辑:程序博客网 时间:2024/04/19 08:51

        转眼间,在建哥这都干了半年了。

        这半年算是我写代码最密集的半年吧,不官方,没套路,单纯的写代码。

        不废话,今天遇到一个难题:

            统一类型的商店,shop1,shop2,shop3. 在表现上,用同一种方式表现。客户端方面,自然统一处理了代码。

            每一个商店对应一个配置表,也就是三张表,我们的导表工具会将它们导成三个类。我在这三个类中取数据,然后统一表现三个商店,于是有了这段代码:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace FictionFather{    class Program    {        static void Main( string [] args )        {            string input = Console.ReadLine();            switch( input ) {                case "1": ShopDay shopDay = new ShopDay();                    Console.WriteLine(string.Format("Shop name is '{0}'", shopDay.name));                    Console.WriteLine(string.Format("Use {0}th money", shopDay.priceType));                    break;                case "2": ShopWeek shopWeek = new ShopWeek();                    Console.WriteLine(string.Format("Shop name is '{0}'", shopWeek.name));                    Console.WriteLine(string.Format("Use {0}th money", shopWeek.priceType));                     break;                case "3": ShopMonth shopMonth = new ShopMonth();                    Console.WriteLine(string.Format("Shop name is '{0}'", shopMonth.name));                    Console.WriteLine(string.Format("Use {0}th money", shopMonth.priceType));                    break;                default: Console.WriteLine("only input 1,2 or 3"); break;            }            Console.ReadLine();        }    }    class ShopDay {        public string name = "DayShop";        public int priceType = 2;    }    class ShopWeek {        public string name = "WeekShop";        public int priceType = 200;    }    class ShopMonth{        public string name = "MonthShop";        public int priceType = 1001;    }}
vs控制台程序大概模拟一下


        注意到没有,我在客户端用了switch,是哪个商店我就去哪个类取数据。你问我为什么不一起处理,这个我当时也是很苦恼,这三个商店类没有兄弟关系(没有共同继承一个父类),尽管他们结构是一样的,但是在语法上不能统一处理。说的有点啰嗦了,其实,本质原因是导表工具当初没有想到会有这种情况,不会套上父类,没有父类而我又不能加这才是最骚的。所以,我只能在客户端用switch。把相同的代码复制出很多份。并且每一个用到表的地方,我都要用一个switch。代码多不说,日后策划想加商店,我得把所有switch都加一个分支。我并不能保证我不会遗漏,麻烦又容易报错,真是哔了狗了。然后我又问策划:因为表的结构一致,可不可以将所有商店的数据配到一张表中,但这样其实我就是把策划给坑了。表的维护难度会大大提升不说,我也不能保证策划是否已经理解了这样配表的意义从而不犯错误。总之,这样不靠谱,人不能总为过去的事买单。于是我问了建哥,建哥说用反射,但是很冒险。

我想了一下反射,




这是用反射的实现过程,日后补充




总之,反射也不是很好,大材小用,而且影响了性能就更麻烦了


就在这时,一段代码以消息的方式出现在我电脑面前。代码末尾处写道:如果不嫌麻烦的话,可以试试这个。

好吧,说的跟黑客什么似的,其实就是有个人给我发QQ,这个人就是明李兄!

明李兄是我的前辈,也是我的校友。是一个思维很敏捷的人

我按照他的想法,将代码改成了:


using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace FictionFather{    class Program    {        static void Main( string [] args )        {            string input = Console.ReadLine();            var shop = ShopManager.GetAShop((ShopType) ( int.Parse(input) ));            if( shop != null )            {                Console.WriteLine(string.Format("Better:Shop name is '{0}'", shop.name));                Console.WriteLine(string.Format("Better:Use {0}th money", shop.priceType));            }            else {                Console.WriteLine("only input 1,2 or 3");            }            Console.ReadLine();        }    }    class ShopDay {        public string name = "DayShop";        public int priceType = 2;    }    class ShopWeek {        public string name = "WeekShop";        public int priceType = 200;    }    class ShopMonth{        public string name = "MonthShop";        public int priceType = 1001;    }    enum ShopType    {        ShopDay = 1,        ShopWeek = 2,        ShopMonth = 3    }    class ShopBase {        public virtual string name { get { return string.Empty; } }        public virtual int priceType { get { return 0; } }    }    class ShopDayBox : ShopBase {        ShopDay info = new ShopDay();        public override string name        {            get            {                return info.name;            }        }        public override int priceType        {            get            {                return info.priceType;            }        }    }    class ShopWeekBox : ShopBase    {        ShopWeek info = new ShopWeek();        public override string name        {            get            {                return info.name;            }        }        public override int priceType        {            get            {                return info.priceType;            }        }    }    class ShopMonthBox : ShopBase    {        ShopMonth info = new ShopMonth();         public override string name        {            get            {                return info.name;            }        }        public override int priceType        {            get            {                return info.priceType;            }        }    }    class ShopManager {        static public ShopBase GetAShop( ShopType type )        {            switch( type )            {                case ShopType.ShopDay: return new ShopDayBox();                case ShopType.ShopWeek: return new ShopWeekBox();                case ShopType.ShopMonth: return new ShopMonthBox();            }            return null;        }    }}

是的,尽管付出了很多代价,但是我的客户端代码没有switch 了。 通过一个manager类管理,其实相当于强行用一个盒子包装,然后几个盒子有兄弟关系,根本问题得以解决。这样的好处是涉及的商店分子在manager添加一个即可, 而且box类如果写错也会被语法检测检查出来。省事,出错概率也很小。不过也许,还会有更好的设计模式。

我反思了一下,最近也看了很多设计模式相关的书《设计模式之禅》、《大话设计模式》等。也画了很多类图,写了很多小例子去理解。但是真正要用到它的时候却显得很无力,只能问别人。这种不能独立思考的状况我把它理解成是没有理解到问题的本质。其实我有一下不足:1语法知识不够坚固,应该多去了解每一个语法产生的意义。2项目实战较少。缺少百炼成钢的过程,以前我总追求效率,其实犯错也是成长的一个过程。


git地址:https://git.oschina.net/WebGL/FictionFather2.git 点击打开链接


0 0
原创粉丝点击