主要是现在这设计模式的文章太多,而且各种烂各种曲解,看的人心烦,烦到忍不住想自己写一个系列把它们说清楚——但是呢,转念一想,我写的再怎么清楚能有GoF清楚呢,怎么能有GoF的影响力大呢,GoF明明白白地摆着,还有这么多人乱搞,我又能做什么呢?所以想了半天,我觉得就写一篇文章来吐槽好了。 - -!
说设计模式这个东西呢,不少网友跟我说起其实叫设计模式是很不对的,我也深有同感。pattern这个词有纹理、花纹的意思,外国人买布买窗帘的时候可能会挑挑pattern,这东西说成是模式就有点过了,所以我觉得这个东西其实翻译成《面向对象设计23招》比较好,这样也跟我朝的《网页特效50例》等畅销书比较对仗。
虽然一些同学对"设计模式"这个好听的词被抢感到不满,认为提到的时候应该加些修饰词,不过为了简单起见,咱们这里约定凡提到"设计模式"皆指GoF23模式。
设计模式针对的是面向对象的设计问题
设计模式的另外一个巨大的问题就是它把面向对象和软件这两个重要的关键词放进副标题里面了,兼之作者非常骚包地在里面扯了一通模式界、建筑学这等事情,搞得好像这书超脱了语言和场景限制,"是一种编程思想"(加引号的原因是我觉得大师们欺骗新手最常见的手段就是故弄玄虚地说"语言都是浮云,编程思想最重要。"),只要写程序就必须模式一下什么的。当然GoF肯定不是故意骗大家了,其实也只能骗到那些只看正标题连副标题也不看的孩子,看了内容的话就更不会搞错了。
但是令我惊讶的是连副标题都不看的人确实不在少数,非要用跟面向对象毫无关系的方法实现设计模式的人真的很多啊......
说了半天其实我这里想说的是设计模式是面向对象编程中特有的一些技巧,是应用五大基本原则之后(单一职责、开放封闭、里氏代换、接口隔离、依赖倒置)产生的一些设计疑难问题的解决手段。在一些非纯的面向对象语言里面可能根本就不需要设计模式。
一个非常明显的例子就是,抽象工厂、工厂方法、原型三个模式要解决的是DIP应用以后的创建对象难题。
很多文章根本就不管什么DIP,举了一堆所谓"生活中的例子",神马造零件做汉堡的copy作业之类的,尼玛啊,这跟那些生活有毛关系啊,程序员的生活难道不就是写程序么?写程序难道不就必然要用到DIP么?用到DIP只依赖接口这东西不能new才需要这几个模式的啊,人家模式名字里面带工厂俩字没听说实现的业务就一定要跟生产有关系啊。
基于这种不知所谓的逻辑,这几个模式当然也可以用在JS、C什么的里面啦,因为JS也难免有描述鞋厂麦当劳的时候嘛。于是这些模式就华丽丽地成为了一种思想,抽象工厂变成了"描述一个一种对象可以产生另外一种对象这样的业务逻辑",原型变成了"描述一个对象可以copy自身这样的业务逻辑",更加华丽地是,这些业务逻辑模式还能被扭来扭曲实现成完全符合GoF上UML图的类结构啊.....
说到正经事,既然是因为遵循DIP才引入的几个模式,在JS这个没有接口的面向对象语言中,自然不存在使用的需求了。(但有趣地是,JS里面把原型作为几乎是唯一地创建对象手段,与本文主题无关,就不多说了。)而C++有模板这样强大的特性,很大程度上也不需要简单工厂和工厂方法(抽象工厂还是需要的)。同样的道理,拥有delegate和Event的C#里面也没有使用观察者模式的必要。
语义比UML重要1000倍
设计模式里面最不容易误解的就是UML了,凡讲设计模式的文章,就算扯得再不靠谱,一般UML也是对的...... 好吧UML也是对的这件事实在太容易,甚至比如策略模式和状态模式和桥接模式的UML都是基本一样的。
嗯,于是囧的事情出现了,比如http://en.wikipedia.org/wiki/Strategy_pattern 在煞有介事地对比策略和桥接到底有何不同。尼玛啊!!!!我怎么没想明白一个叫"实现",一个叫"算法",这俩东西肿么就能有交叉呢?
只看UML是不少设计模式文章的通病,嗯,通常情况下这时候"生活中的例子"又会登场了,语义则会被华丽丽地无视。最为悲惨的两个模式就是策略模式和桥接模式了,看来"算法"、"实现"、"抽象"这些词实在不太好理解。为了够"生活",譬如买油和买盐这等完全不相干的功能就被戴上了算法的帽子,GoF说的好"本模式使得算法可以独立于使用它的Client而变化",Client表示很无奈啊,就换了个算法而已,连结果都变了是怎么回事啊,刚才算的还是a+b,尼玛你一换算法结果变成a*b了?(嗯, 我在吐槽http://en.wikipedia.org/wiki/Strategy_pattern) 卧槽你想说a+b和a*b都是calculate这件事么?你怎么不干脆把所有方法都叫dosomething啊,那样全世界所有的事情都可以叫不同策略了啊!
桥接模式更悲剧了,"抽象"和"实现"这俩词怎么听着这么像接口和具体类啊,难道说......桥接模式其实就是LSP?再一看UML真简单啊,这不就是组合么?于是乱搞一个"生活中的例子"把UML对上就成了!我承认英文里面这俩词跟实现接口、抽象类有点像,翻译成中文更没区别了,但是GoF里面不是tmd还有例子呢么?不是还有解释呢么?GoF那Window的例子是多么的明显,抽象是业务相关的,实现是系统底层相关的。
一些其它的模式和误解
Flyweight经常被以C#的字符串为例而搞成"神秘地节约内存方案",或者以内存池为例搞成只有外部状态的假对象。辨识正确的Flyweight模式实现的关键要素是内部状态和外部状态是否俱全。
Composite模式经常被误解为树形结构,辨识Composite模式的关键在于语义,几个X的组合是否仍然是X,而不是被X包含。举例子来说,几个几何图形的组合仍然是几何图形,而几个HTML节点的组合就不是一个HTML节点。
Decorator模式经常被搞成拼字符串用的(尼玛,这活还是交给StringBuilder之类的东西吧......),辨识Decorator的关键一是被装饰的是类而不是方法,二是语义上是否可以被再次装饰。
结语
设计这件事情很难用语言表达,因此要讲清楚设计是一件非常困难的事情,在博客园出现的设计模式文章我经常跑去给负面评论......但屡屡被教育"不要为了模式而模式"、"你对设计模式的理解,还仅限于GoF"、"只要遵循基本设计原则就可以"。(大约我朝受"无招胜有招"文化熏陶太久,导致大家还没等学会招呢,先奔无招去了......)设计模式的本意之一是提供一套通用的设计词汇,但是显然时至今日(至少在我朝),它自身都被各种歪曲误解。希望大家能够一起努力,一是以身作则,写文章的时候更严谨,二是擦亮眼睛,看文章的时候多查资料,消灭设计模式的各种歪解
分享到:
相关推荐
国科大刘成林教授开设的模式识别课程所用教材及课后习题答案
android 观察者模式源码demo 博客地址 http://blog.csdn.net/shaoyezhangliwei/article/details/54019131
1、序 2、商业推广 3、无敌的商业心理学 4、再见营销引流 5、这是个什么鬼 6、互动式心理学 7、常规性总结
你可能熟悉典型的“瀑布模式”的开发过程:从系统需求分析开始,然后着手设计,接着开始前后台开发,最后进行评估并且实施。线性性质是瀑布式开发的主要特点:当这一阶段完成,下一阶段紧接开始,两者配合的几乎...
分钟内与团队再见 不要忘记给我们留下评论。 示例 Java 文件 src/com/in28minutes/patterns/AdapterPattern.java package com.in28minutes.patterns; import java.util.ArrayList; import java.util.Arrays; import ...
它具有以下执行模式: -daemon :进程连续运行,并每5分钟获取一次关注者(或指定的$GOODBYE_POLLING_INTERVAL )。 不需要额外的存储空间即可存储关注者列表(存储在内存中)。 -http-addr :进程在指定的端口上...
给大家介绍一种全新的设计方法,只需要五个步骤
Scratch Bricks 入门指南 [兼容模式].pdf
小型项目 ...由于这是一个非常“原型”的区域,一定会在一段时间后变成混乱的混乱状态。 它应该不时清理。 --->(也许将内容复制到单独的文件夹中?...再见,再见,桑德罗,再见,再见,马塞尔 进一步测试...
一个美国人公布了一个很“酷”的安装Debian的软件,叫做debian.exe,公布在“再见-微软”网址上([url]http://goodbye-microsoft.com/[/url])。在Windows XP下直接运行这个软件。就可以装一个独立的Debian系统(不是...
帕累托原则,也称为80/20规则,描述了这种常见的销售集中模式。 但是,一般的信息技术,尤其是互联网市场,有可能大幅增加利基产品的集体份额,从而在销售分配中产生更长的尾巴。 本文研究了互联网的“长尾巴”现象...
再见文字 用java做第一次测试。 该应用程序将要求提供一些数据(注册和取消日期、平均每月供款基数等),并将返回与各种解雇类型(资历、补偿等)相关的信息。
这套源码是基于FineCMS2.5.0高级版修改而来,将目录结构调整为CodeIgniter建议模式,在加载配置的方式上还原了CI原版的优雅方式,关于URL分段的问题,尚依原版的样式.有兴趣的同学可以接着修改. 这是一套非常适合学习...
探探是一款基于地理...使用者可以在探探上通过左右滑动认识附近的人,左滑再见,右滑喜欢。探探App交友流程可以简单理解为“彼此喜欢->享受一刻心动的小惊喜->开始聊天”模式。探探可以免费发送文字消息、语音、照片
再见! 演示版 在在线查找最终代码 概述 使用RxJ实时处理流。 在本讲座中,您将获得Reactive-Extensions的概述,并在实时编码会话中看到它的用法。 首先,您将了解Rx及其历史。 在介绍了基本概念和术语之后,我们将...
hp测试任务用法cp .env.docker .envdocker-compose up -d && docker-compose logs -f待办事项清单 环境 码头工人组成3.7 ... 模式“代理”,表“请求” 将标识符返回给请求者 产生消息给kafkas的主题A 等待来自服
目前,网络考试系统的实现,可以采用传统的客户机/服务器模式,也可以采用目前流行的浏览器/服务器模式,即基于Web的方式。本系统采用的后一种模式,因此,本文简单的介绍了该模式的实现方法。同时,还介绍了等级...
目前国内使用和发展的MIS 平台模式大体有两种:客户机/服务器(Client/Server,简称C/S)模式和Web浏览器/服务器(Browser/Server,简称B/S)模式。利用某个开发平台结合C/S模式实现一个信息管理系统,在目前还是比较...
最终幻想英雄Android示例应用程序测试了一些很酷的库和模式: Dagger 2(创建此项目的主要理由是要学习此项目) 改造(如果没有它,您甚至如何使用API ???) RxJava + RxAndroid(一定喜欢一些函数式编程-和...
该文件由不同的意图组成:每个意图都收集用户编写的一些模式(问题),这些模式针对侧重于冠状病毒(什么是冠状病毒,其症状,如何佩戴口罩等)以及相关标签的不同主题(或标签)。 这使我们能够以监督的方式训练...