记录自己学习设计模式的路程,并和大家分享。如果有不对的地方,欢迎指正。
PS:做.NET的
关于设计模式
我有2个搞JAVA的同事,只要我和他们一谈起设计模式,他们就是不屑一顾的表情,当我在项目中遇到一些诸如如何处理类之间的关系的问题的时候,他们又推荐我看看设计模式,难道是要拿我试水吗?看设计模式好用吗?好让他们也脱离COPY+PASTE的重复劳动吗?恩,这个世界是懒人推动的,同意的有木有?
好的,言归正传,不知道大家有没有发现,其实你看了设计模式的书,如果你没有亲自在实践中去体会过,可能还是会一头雾水,特别是初步接触面向对象开发的朋友,你的脑子当中会出现无数个为什么,为什么要封装,为什么要抽象;其实对于你现在的项目而言,只要你的项目不是企业级,只要你的项目还未上线,只要你的项目是随时可编译可发布,只要你的项目基本不和别人对接,还有N种只要,那你用不用设计模式都是那么大点事,一个对象你封装不封装对你写代码而言没有很大影响,说不定完成封装就会加大你的代码量,就算是需求有变更,OK,进入你的类内部,修改一下方法,恩,差不多了。
设计是一种艺术,其实我也没有很多经验,对于现在的我来说,看看设计模式就是感受一下头脑风暴,很多模式的应用场景我还没有碰见过,我只能用脑袋去想,恩,说专业点叫做意淫。太极没玩儿过总看过吧?其实设计模式相对于现在的我来说就是四两,我开发的项目也是四两,如果我开发的项目是千斤的时候,设计模式就会有四两拨千斤的惊艳效果。
关于面向对象
恩,面向对象,有太多人告诉我,我们写的是面向对象的程序,每个人思维都不一样,面向对象的好处是什么,好扩展,好维护,好复用;
好复用是什么?就是拿到哪基本都可用,或者说是做尽量少的修改就可复用;但是要做到复用,恩,通常是要修改很大和很多次的,所以尽量少基本忽略,不管你写的是功能上的组件还是业务组件,拿到什么地方都能让别人一目了然的调用,甚至可以扩展;别人需要知道的仅仅只是你组件如何去调用,如何去扩展,其他的不用关心;
好扩展是什么?你会认为就只有你自己会对你自己的组件进行扩展吗?你会认为别人扩展就是继承你组件里面的类,然后再加点方法吗?恩,你会用internal的吧?
好维护是什么啊?就小项目而言,基本不存在,只要CODER知道代码是怎么运行的就可以了;大项目呢,企业级的用SPRING的呢?
好的,你自己写的面向对象的组件,请拿出你的标准,别人要复用,要扩展,要维护需要什么样的标准,不仅仅是别人,请你自己也遵守这个标准;什么最赚钱,标准最赚钱啊,人家要用你的标准就要给钱啊。
呵呵,是不是高人也看的很迷糊啊?请理解一下,我措辞不清,思路不清晰;我的方法就是,如果你在写一个类,请将角度调整到这个类身上,它有什么样的职责,它需要封装一些什么,它对外有什么样的接口,它如何来完成它的职责,它有什么样的标准?
那么开始吧。
策略模式
先说一说设计模式的原则,优先使用类的组合,而不是继承;其实这句话蛮偏激,就和很多人使用类的继承也使用的蛮偏激一样,正因为继承被用的偏激了,所以原则也要偏激一点;什么都要讲究中庸之道,如果有一个抽象类,你有很多类继承于它,当然,都和这个抽象类有关系,不管是重写抽象类的方法,还是继承抽象类的字段等等;如果有3个子类,可以忍受,如果有10个呐?需求变更,跑到10个地方去OVERRIDE吗?要继续扩展,继续增加子类吗?
这就是泛滥了,如果我们把OVERRIDE的方法抽离出来,换成一种标准,可以吗?恩,你先不要思考什么是标准,因为都是抽象的素语,你就不要管它到底是个什么玩意儿了,你只需要想,现在有一种标准,它可以完成你所有子类中要OVERRIDE的方法中的行为。
好的,我们再说说另外一个,现在你的代码中某一个地方有很多SWITCH CASE,其实你并没有什么感觉的,是不,只要它能完成相应的功能;可能你某天想到了,把它封装成了一个工厂,恭喜你,你抽象了;但就本质来说,其实是把逻辑分支从原来那移动到了工厂内部,逻辑分支还是要有,只不过换了个地儿,有什么好处呢?想远一点,你可以这样说,这就是你的标准,想扩展吗?请到工厂增加一个分支,调用这个工厂的类是不需要做任何变动的,再远一点,你可以用各种技术在工厂内部规避写IF ELSE或者SWITCH,比如反射,这就扯远了,究其本质,你原来写分支的地方其实是在依赖分支,现在是在依赖工厂,换成素语就是,你本来是在依赖细节,现在依赖于抽象了。
正式开始策略模式:
什么是策略?策略就是你想干一件事,达成这件事的方法,够通俗了吧?把这些策略都抽象出来,就OK了
你今天想泡一个妹子,你想到了很多种方法,这些方法适用在不同的场合:
- 以一个无比2B的开场吸引她的注意
- 用眼神挑逗她,告诉她你在发春
- 邀请她去逛菜市场
1-3就是你要泡这个妹子的策略,把你想到的这3点写在你的把妹专用日记本上,到了哪一个程度你就使用哪一个策略;好的,我们能面向对象一下吗?如果这个CLASS就是你,你不会想要做个抽象类吧?然后让3个儿子重写你把妹的行为去把同一个妹子?那么我们应该怎么做呢?
好的,我先把我的把妹专用日记本SHOW一下
1 public interface IChase
2 {
3 string Chase();
4 }
再把我的策略SHOW出来
1 public class EncounterBy2B : IChase
2 {
3 public string Chase()
4 {
5 return "我要在她看到我的那一瞬间被我2B的样子深深吸引";
6 }
7 }
8
9 public class UseEyes : IChase
10 {
11 public string Chase()
12 {
13 return "眼神够不够春?尽量散发春的气息";
14 }
15 }
16
17 public class GoToMarket : IChase
18 {
19 public string Chase()
20 {
21 return "其实邀请她来菜市场,是让她明白,我讨价还价的本领绝对比大妈厉害";
22 }
23 }
我呢?把我自己也描绘出来吧
1 public class Peter
2 {
3 private IChase _chaseNote;
4
5 ///<summary>
6 /// 我要开始选择把妹的策略了
7 ///</summary>
8 public void SelectChaseMethod(IChase chaseNote)
9 {
10 this._chaseNote = chaseNote;
11 }
12
13 ///<summary>
14 /// 应用把妹的策略
15 ///</summary>
16 public void BeignChase()
17 {
18 _chaseNote.Chase();
19 }
20 }
好的,把场景描述出来吧
//Peter在路上等着她想等的妹子
Peter peter = new Peter();
//妹子出现了,Peter开始选择策略了
peter.SelectChaseMethod(new EncounterBy2B());
//Peter开始应用2B策略
peter.BeignChase();
恩,后面2个策略就不用写都明白了三。
总结一下,这里策略其实还可以封装在一个工厂里面;恩 Peter就是一个组件哟,你可以用在任何可以演故事的地方哟;Peter有一个把妹专用日记本的标准哟,如果你想让Peter有更多可以把妹的策略,请按照他的标准将他的把妹策略写好吧。其实你不用管Peter的标准是什么,标准就是抽象,所以你不用绞尽脑汁想抽象的是个什么玩意儿,只管用就好了。恩,对了,ArrayList的Sort方法。
我相信我对策略模式的理解还有很多纰漏,欢迎大家指正与交流。