当前位置: 首页 > 编程日记 > 正文

【转】解密“设计模式”

有些人问我,你说学习操作系统的最好办法是学习程序设计。那我们是不是应该学习一些“设计模式”(design patterns)。这是一个我很早就有定论,而且经过实践检验的问题,所以想在这里做一个总结。

总的来说,如果光从字面上讲,程序里确实是有一些“模式”可以发掘的。因为你总是可以借鉴以前的经验,用来构造新的程序。你可以把这种经验叫做“模式”。可是自从《设计模式》(通常叫做 GoF,“Gang of Four”,“四人帮”)这本书在 1994 年发表以来,“设计模式”这个词有了新的,扭曲的含义。它变成了一种教条,带来了公司里程序的严重复杂化以及效率低下。

Design Patterns

GoF 借鉴的是一个叫 Christopher Alexander 的建筑师的做法。Alexander 给一些建筑学里的“设计模式”起了名字,试图让建筑师们有一些“共同语言”。可惜的是,Alexander 后来自己都承认,他的实验失败了。因为这些固定的模式,并没能有效地传递精髓的知识,没能让新手成长为出色的建筑师。

照搬模式东拼西凑,而不能抓住事物的本质,没有“灵感”,其实是设计不出好东西的。这就像照搬“模版”把作文写得再好,也成不了作家一样。

我孤陋寡闻,当听说这本书的时候,我已经学会了函数式编程,正在 Cornell 读 PhD,专攻程序语言设计。有一天由于好奇这书为什么名气这么大,我从图书馆借了一本回来看。我很快的发现,其实这本书的作者只是给早已经存在的编程方法起了一些新的名字而已。当时我就拿起一张纸,把所有的20来个设计模式跟我常用的编程概念做了一个映射。这个映射居然是“多对一”(many-to-one)的。也就是说,多个 GoF 设计模式,居然只对应同一个我每天都用的概念。有些概念是如此的不值一提,以至于我根本不需要一个名字来描述它,更不要说多个名字!

其中极少数值得一提的“模式”,也许是 visitor 和 interpreter。很可惜的是,只有很少的人明白如何使用它们。所谓的 visitor,本质上就是函数式语言里的含有“模式匹配”(pattern matching)的递归函数。在函数式语言里,这是多么轻松的事情。可是因为 Java 没有模式匹配,所以很多需要类似功能的人就得使用 visitor pattern。为了所谓的“通用性”,他们往往把 visitor pattern 搞出多层继承关系,让你转几道弯也搞不清楚到底哪个 visitor 才是干实事的。

其实,函数式语言的研究者们早就知道 visitor pattern 是怎么得来的。如果你想知道如何从无到有,一步一步“发明”出 Java 的 visitor pattern,可以参考《A Little Java, A Few Patterns》(发表于 1997 年)。

little java

而 interpreter (解释器)模式呢?看了作者们写的例子程序之后,我发现他们其实并不会写解释器,或者说他们不知道如何写出优雅的,正确的解释器。如果你想知道如何写出好的解释器,可以参考我的博文《怎样写一个解释器》。

你说我在贬低这本书的真正价值,因为 GoF 说了:“我们的贡献,就是给这些编程方式起名字。这样让广大程序员有共同的语言。” 如果这也叫贡献的话,我就可以写本书,给“空气”,“水”,“猪肉”这些东西全都起个新名字,让大家有“共同的语言”。这不是搞笑吗。

这不是我的一家之言,Peter Norvig 在 1998 年就做了一个演讲,指出在“动态语言”里面,GoF 的20几个模式,其中绝大部分都“透明”了。也就是说,你根本感觉不到它们的存在。这就像我刚才告诉你的。

Norvig talk

在这里 Norvig 的观点是正确的,不过需要小心一个概念错误。Norvig 对“静态语言”的概念是有局限性的。有的静态语言其实也能传递函数作为参数,而且不像 Java 那样什么都得放进 class 里。这样的静态语言,其实也可以避免大部分 GoF 设计模式。而“动态语言”这个概念,在程序语言的理论里面,其实是没有明确的定义的。“动态语言”其实也能进行某些“静态类型检查”。不过在 1998 年,我还是个啥都不懂的屁孩,所以这里就不跟 Norvig 大叔计较了。

既然老人们都有历史局限性,那么为啥我还跟 GoF 找茬?本来这本书很老了,如果没有人再被它误导的话,这篇博文也就不必存在了。可是当我在 Google 实习的时候,我发现几乎每个程序员的书架上都有一本 GoF!我在 Google 实习了两次,第一次的时候代码全都是我一个人写的,所以没有使用任何 GoF 设计模式。代码直接,精巧而简单。当我第二次回到 Google,发现我的代码里已经被加入了各种 factory,visitor,…… 其实啥好事也没做,只不过让我的代码弯了几道弯,让人难以理解。

可见一本坏书,毁掉的不只是一代程序员。鉴于如此,特发此文。各位新手,希望你们敲响警钟,不要再走上这条老路,写出代码来让大家痛苦。

转载于:https://www.cnblogs.com/alantu2018/p/8495734.html

相关文章:

Qt Installer Framework实战

Qt Installer Framework是Qt发布的安装程序支持框架,只需要简单的配置就可以生成安装文件,同时可以通过javascript脚本来定制安装过程。 目录结构 config packages data meta 配置文件 config/config.xml packages/[product]/meta/package.xml packages/…

【NCEPU】徐韬:街景字符编码识别比赛

徐韬是华北电力大学数理系大四的学生,Datawhale成员/Dreamtech成员,参加了多期Datawhale的组队学习,也在天池/CCF/讯飞等比赛中取得了不错的成绩,现保送大连理工大学深造。 这篇图文是他在线下组队学习时,为大家分享自…

java 程序启动界面_程序启动界面java代码

最近写了个程序启动界面,分享一下import javax.swing.*;import java.awt.*;import java.net.*;//Download by http://www.codefans.net//程序启动界面/*dkplus专业搜集和编写实用电脑软件教程,*搜集各种软件资源和计算机周边,独立制作视频和p…

中国电子学会图形化四级编程题:食堂取餐

「青少年编程竞赛交流群」已成立(适合6至18周岁的青少年),公众号后台回复【Scratch】或【Python】,即可进入。如果加入了之前的社群不需要重复加入。 我们将有关编程题目的教学视频已经发布到抖音号21252972100,小马老…

获取app传入的json值处理

$getDatas $_POST; if(empty($getDatas)) $getDatas file_get_contents("php://input"); $getDatas json_decode($getDatas,true); 转载于:https://www.cnblogs.com/wjw-/p/8496855.html

java虚拟机栈帧_Java虚拟机,运行时栈帧结构

业余生活要有意义,不要越轨。——华盛顿引导语“虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统层面上的,而虚拟机的执行引擎则是由软件…

深入浅出Pytorch:01 课程大纲与PyTorch简介

深入浅出Pytorch 01 课程大纲与PyTorch简介 内容属性:深度学习(实践)专题航路开辟者:李嘉骐、牛志康、刘洋、陈安东领航员:叶志雄航海士:李嘉骐、牛志康、刘洋、陈安东开源内容:https://githu…

用C写有面向对象特点的程序

比如在一个项目中,有大量的数据结构,他们都是双向链表,但又想共用一套对链表的操作算法,这怎么做到呢,C中又没有C中的继承,不然我可以继承一父(类中只有两个指针,一个向前一个向后&a…

[置顶] 单键模式的C++描述

设计模式-单键(Signelton):其实单键的设计模式说来很简单,说的直白一点就是程序运行过程中保证只有一个实例在运行而已。在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑…

下java7 64有什么用_Win 7 64位系统安装java 8,看完就明白了

在 Windows 7 的 64 位系统中安装 jdk 8工具/材料Windows 7 64 位系统JDK 8 64位版本方法/步骤1 下载JDK 8安装文件011.1 访问JDK下载地址http://www.oracle.com/technetwork/java/javase/downloads/index.html点击 JDK Download 按钮,进入JDK下载页。021.2 下载JDK…

微软BI 之SSAS 系列 - 在 SQL Server 2012 下查看 SSAS 分析服务的模型以及几个模型的简单介绍...

在SSDT中部署一个 SSAS 项目到本地服务器上出现错误。 You cannot deploy the model because the localhost deployment server is not running in multidimensional mode。 错误原因是因为我在本地安装 SQL Server 2012 的时候只选择安装了 Tabular Mode,而这个Dem…

java遍历的优化

说明&#xff1a;这是在面试中面试官出的题。虽然是常见的优化问题&#xff0c;但这种经验的确很有用。感慨之余&#xff0c;分享出来&#xff0c;以此共勉。 场景&#xff1a;现有List<PersonA>,List<PersonB>,PersonA 的属性是 String类型的身份证号&#xff0c;…

深入浅出Pytorch:02 PyTorch基础知识

深入浅出Pytorch 02 PyTorch基础知识 内容属性&#xff1a;深度学习&#xff08;实践&#xff09;专题航路开辟者&#xff1a;李嘉骐、牛志康、刘洋、陈安东领航员&#xff1a;叶志雄航海士&#xff1a;李嘉骐、牛志康、刘洋、陈安东开源内容&#xff1a;https://github.com/…

java for 两个条件_for循环条件里定义2个变量为什么会报错

public class HelloWorld {//完成 main 方法public static void main(String[] args) {int scores[]{89,-23,64,91,119,52,73};HelloWorld hellonew HelloWorld();hello.sortScore(scores);}//定义方法完成成绩排序并输出前三名的功能public void sortScore(int[] scores){Arra…

Qt4在linux下的安装

1、下载SDK ftp://ftp.informatik.hu-berlin.de/pub/Mirrors/ftp.troll.no/QT/qtsdk/qt-sdk-linux-x86-opensource-2010.05.1.bin 2、修改文件权限 想要安装SDK&#xff0c;需要拥有对其读写和执行的权限。可以通过【右键】->【属性】->【权限】进行设置。 也可以通过命…

高性能千万级定时任务管理服务forsun使用详解

Forsun高性能高精度定时服务&#xff0c;轻松管理千万级定时任务。项目地址&#xff1a; https://github.com/snower/forsun 使用 linux 系统定时器提供精确到秒级的定时调度&#xff0c;长时间运行保证无误差。支持本地内存存储和 redis 持久化存储&#xff0c;使用 redis 可轻…

谢文睿:西瓜书 + 南瓜书 吃瓜系列 11. 贝叶斯分类器

吃瓜教程——西瓜书南瓜书 Datawhale南瓜书是经典机器学习教材《机器学习》&#xff08;西瓜书&#xff09;的公式推导解析指南&#xff0c;旨在让在学习西瓜书的过程中&#xff0c;再也没有难推的公式&#xff0c;学好机器学习。 内容属性&#xff1a;机器学习&#xff08;理…

java 上传的图片大小为0_JAVA技术:上传图片的缩放处理

图片上传到后&#xff0c;会根据情况将图片缩小成一个图标&#xff0c;我们可以利用java强大的图形处理功能&#xff0c;对上传的图片进行缩放处理。下面的程序使用jdk1.4中最新的ImageIO对图片进行读写。使用AffineTransform对图片进行缩放。import java.io.File&#xff1b;i…

信息安全推荐书籍

本页列出了我发现的与计算机安全&#xff0c;数字取证&#xff0c;事件响应&#xff0c;恶意软件分析和逆向工程以及其他相关主题学习主题高度相关和有用的书籍。这些书从介绍性文本到高级研究作品。尽管这些书中的一些看起来有点过时&#xff0c;但所包含的信息对今天学习的人…

paip.odbc DSN的存储与读取

paip.odbc DSN的存储与读取 作者Attilax &#xff0c; EMAIL:1466519819qq.com 来源&#xff1a;attilax的专栏 地址&#xff1a;http://blog.csdn.net/attilax 1.列出系统级ODBC列表 ---------------------- [HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ODBC Data So…

【青少年编程】【三级】计算平均分

「青少年编程竞赛交流群」已成立&#xff08;适合6至18周岁的青少年&#xff09;&#xff0c;公众号后台回复【Scratch】或【Python】&#xff0c;即可进入。如果加入了之前的社群不需要重复加入。 我们将有关编程题目的教学视频已经发布到抖音号21252972100&#xff0c;小马老…

java 判断是否为邮箱_Java判断邮箱是否存在 有返回值

public static boolean checkEmail(String email) {if (!email.matches("[\\w\\.\\-]([\\w\\-]\\.)[\\w\\-]")) {return false;}String log "";String host "";String hostName email.split("")[1];// 去掉后面的System.out.printl…

Android Handler介绍

本文转自:http://www.cnblogs.com/keyindex/articles/1822463.html前言 学习android一段时间了&#xff0c;为了进一步了解android的应用是如何设计开发的&#xff0c;决定详细研究几个开源的android应用。从一些开源应用中吸收点东西&#xff0c;一边进行量的积累&#xff0c;…

阿里巴巴一年投三家AR公司,AR购物或是最终目标

阿里巴巴再投资AR公司&#xff0c;一年连续投资超2.2亿美元&#xff0c;它到底想要做什么&#xff1f; 最近&#xff0c;以色列AR眼镜厂商Lumus获得来自阿里巴巴的600万美元的投资。此前&#xff0c;镁客网报道过这家公司在去年12月份获得由广达电脑、HTC和盛大集团投资的300万…

青少年编程竞赛交流群周报(第035周)

2021年10月24日&#xff08;周日&#xff09;晚20:00我们在青少年编程竞赛交流群开展了第三十五期直播活动。 一、直播内容 我们直播活动的主要内容如下&#xff1a; 讲解了上次测试中小朋友们做错的题目 Scratch青少年编程能力等级测试模拟题&#xff08;四级&#xff09;。…

java 接口工程_Java工程师(15)抽象类与接口

抽象类思考下面程序潜在的问题交通工具中定义了4个方法&#xff0c;其中行驶方法内部会依次调用启动、加速、停止方法。由于不同的交通工具&#xff0c;启动的方式差异很大&#xff0c;所以交通工具类中并不实现该方法&#xff0c;而是将其交给子类实现。上述代码的问题&#x…

为什么必须是final的呢?

一个谜团 如果你用过类似guava这种“伪函数式编程”风格的library的话&#xff0c;那下面这种风格的代码对你来说应该不陌生&#xff1a; 1 2 3 4 5 6 7 8 9public void tryUsingGuava() {final int expectedLength 4;Iterables.filter(Lists.newArrayList("123", &…

java mvc view_对Springmvc view层的理解

MVC框架可以把应用清晰明了地分为三个部分&#xff1a;Model层–数据层&#xff0c;View层–视图层&#xff0c;Controller–逻辑层&#xff0c;Model层负责整合数据&#xff0c;View层负责页面渲染&#xff0c;Controller层负责实现业务逻辑。我在这里简单说一下我对MVC框架中…

【优秀作业】粒子群算法

粒子群优化算法 一、概述 粒子群优化算法&#xff08;Particle Swarm Optimization&#xff0c;PSO&#xff09;的思想来源于对鸟捕食行为的模仿&#xff0c;最初&#xff0c;Reynolds.Heppner 等科学家研究的是鸟类飞行的美学和那些能使鸟群同时突然改变方向&#xff0c;分散…