封面

版权信息

内容简介

NOTE

GoF(设计模式的经典名著——Design Patterns:Elements of Reusable Object-Oriented Software,中译本名为《设计模式——可复用面向对象软件的基础》的四位作者Erich Gamma、Richard Helm、Ralph Johnson,以及John Vlissides,这四人常被称为Gang of Four,即四人组,简称GoF)

2022-03-16 19:48:43

文前

本书出版后的读者评论

卓越亚马逊的本书读者评论

互动出版网的本书读者评论

第二书店的本书读者评论

CSDN读书频道的本书读者评论

作者博客的本书读者评论

本书策划编辑对本书的评论

CSDN 2007年度十大精品图书第1名

前言

本书起因

本书读者

本书定位

NOTE

如果说我比别人看得更远些,那是因为我站在了巨人的肩上。

2022-03-16 20:17:39

本书特色

本书内容

本书人物及背景

本书研读方法

关于本书学习的疑问解答

编程语言的差异

不是一个人在战斗

第1章 代码无错就是优?——简单工厂模式

1.2 初学者代码毛病

1.3 代码规范

1.4 面向对象编程

NOTE

这个我学过,只不过当时我没想到而已

2022-03-17 02:37:21

NOTE

碰到问题就直觉地用计算机能够理解的逻辑来描述和表达待解决的问题及具体的求解过程

2022-03-17 02:37:33

NOTE

用计算机的方式去思考,比如计算器这个程序,先要求输入两个数和运算符号,然后根据运算符号判断选择如何运算,得到结果,这本身没有错,但这样的思维却使得我们的程序只为满足实现当前的需求,程序不容易维护,不容易扩展,更不容易复用。从而达不到高质量代码的要求。

2022-03-17 02:37:47

1.5 活字印刷,面向对象

1.6 面向对象的好处

NOTE

客户的要求也并不过份,不就是改几个字吗,但面对已完成的程序代码,却是需要几乎重头来过的尴尬,这实在是痛苦不堪。说白了,原因就是因为我们原先所写的程序,不容易维护,灵活性差,不容易扩展,更谈不上复用,因此面对需求变化,加班加点,对程序动大手术的那种无奈也就成了非常正常的事了

2022-03-17 02:39:53

NOTE

封装、继承、多态把程序的耦合度降低,传统印刷术的问题就在于所有的字都刻在同一版面上造成耦合度太高所致,开始用设计模式使得程序更加的灵活,容易修改,并且易于复用

2022-03-17 02:40:06

1.7 复制vs.复用

NOTE

编程有一原则,就是用尽可能的办法去避免重复

2022-03-17 02:40:52

NOTE

你写的这段代码,有哪些是和控制台无关的,而只是和计算器有关的

2022-03-17 02:41:03

1.8 业务的封装

NOTE

我就可以复用这个运算类(Operation)了

2022-03-17 02:42:18

1.9 紧耦合vs.松耦合

NOTE

问题是你要加一个平方根运算,却需要让加减乘除的运算都得来参与编译,如果你一不小心,把加法运算改成了减法,这岂不是大大的糟糕

2022-03-17 02:43:45

NOTE

我如何让计算器知道我是希望用哪一个算法呢?”

2022-03-17 12:26:01

1.10 简单工厂模式

NOTE

如何去实例化对象的问题

2022-03-17 12:26:18

NOTE

简单工厂模式’

2022-03-17 12:26:23

NOTE

,到底要实例化谁,将来会不会增加实例化的对象,比如增加开根运算,这是很容易变化的地方,应该考虑用一个单独的类来做这个创造实例的过程,这就是工厂,来,我们看看这个类如何写。

2022-03-17 12:26:36

NOTE

工厂就实例化出合适的对象,通过多态,返回父类的方式实现了计算器的结果。

2022-03-17 12:28:23

NOTE

客户端代码

2022-03-17 12:28:31

NOTE

面的实现就是这样的代码,不管你是控制台程序,Windows程序,Web程序,PDA或手机程序,都可以用这段代码来实现计算器的功能,如果有一天我们需要更改加法运算,我们只需要改哪里

2022-03-17 12:29:05

NOTE

改OperationAdd就可以了

2022-03-17 12:29:19

NOTE

只要增加相应的运算子类就可以了呀

2022-03-17 12:29:33

NOTE

运算类工厂,在switch中增加分支

2022-03-17 12:29:49

1.11 UML类图

NOTE

棒棒糖表示法

2022-03-17 12:38:12

NOTE

鸭子本来也有语言,只不过只有唐老鸭是能讲人话的鸭子

2022-03-17 12:38:41

NOTE

我让它实现了飞翔接口。实现接口用空心三角形+虚线来表示。

2022-03-17 12:39:18

NOTE

当一个类‘知道’另一个类时,可以用关联(association)。关联关系用实线箭头来表示

2022-03-17 12:42:49

NOTE

。所以它们之间就满足聚合(Aggregation)关系。聚合表示一种弱的‘拥有’关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分[DPE](DPE表示此句摘自《设计模式》(第2版)

2022-03-17 12:43:35

NOTE

原来一个小小的计算器也可以写出这么精彩的代码,谢谢大鸟

2022-03-17 12:44:55

第2章 商场促销——策略模式

2.2 增加打折

NOTE

像Convert.ToDouble(),你这里就写了8遍,而且4个分支要执行的语句除了打折多少以外几乎没什么不同,应该考虑重构一下

2022-03-17 18:09:23

2.3 简单工厂实现

NOTE

类的划分是为了封装

2022-03-17 18:33:52

NOTE

是收费对象生成工厂才准确。说得不错,如果我现在需要增加一种商场促销手段,满100积分10

2022-03-18 09:32:55

NOTE

2022-03-18 09:32:59

NOTE

简单工厂模式虽然也能解决这个问题,但这个模式只是解决对象的创建问题,而且由于工厂本身包括了所有的收费方式,商场是可能经常性地更改打折额度和返利额度,每次维护或扩展收费方式都要改动这个工厂,以致代码需重新编译部署,这真的是很糟糕的处理方式,所以用它不是最好的办法

2022-03-18 09:33:43

2.4 策略模式

NOTE

小菜次日来找大鸟,说:“我找到相关的设计模式了,应该是策略模式(Strategy)。策略模式定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。看来商场收银系统应该考虑用策略模式?”策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。[DP]

2022-06-15 19:12:58

NOTE

但算法本身只是一种策略,最重要的是这些算法是随时都可能互相替换的,这就是变化点,而封装变化点是我们面向对象的一种很重要的思维方式

2022-03-18 09:41:40

2.5 策略模式实现

NOTE

我昨天写的CashSuper就是抽象策略,而正常收费CashNormal、打折收费CashRebate和返利收费CashReturn就是三个具体策略,也就是策略模式中说的具体

2022-03-18 11:36:11

NOTE

你有没有什么好办法,把这个判断的过程从客户端程序转移走呢?

2022-03-18 10:22:13

2.6 策略与简单工厂结合

NOTE

原来简单工厂模式并非只有建一个工厂类的做法,还可以这样子做

2022-03-18 12:03:01

NOTE

你的意思是说,简单工厂模式我需要让客户端认识两个类, CashSuper和CashFactory,而策略模式与简单工厂结合的用法,客户端就只需要认识一个类CashContext就可以了。耦合更加降低。

2022-03-18 12:04:13

2.7 策略模式解析

NOTE

所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合[DPE]

2022-03-18 12:08:47

NOTE

策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能[DP]

2022-03-18 12:08:59

NOTE

简化了单元测试

2022-03-18 12:09:32

NOTE

通过自己的接口单独测试

2022-03-18 12:09:52

NOTE

当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为。将这些行为封装在一个个独立的Strategy类中,可以在使用这些行为的类中消除条件语句

2022-03-18 12:10:48

NOTE

任何需求的变更都是需要成本的

2022-03-18 12:11:43

NOTE

这个办法就是用到了反射技术,不是常有人讲,‘反射反射,程序员的快乐’

2022-03-18 12:12:05

第3章 拍摄UFO——单一职责原则

3.2 拍摄

3.3 没用的东西

3.4 单一职责原则

NOTE

大多数时候,一件产品简单一些,职责单一一些,或许是更好的选择。这就和设计模式中的一大原则——单一职责的道理是一样的

2022-03-18 12:25:04

3.5 方块游戏的设计

NOTE

首先它方块下落动画的原理是画四个小方块,擦掉,然后再在下一行画四个方块。不断地绘出和擦掉就形成了动画,所以应该要有画和擦方块的代码。然后左右键实现左移和右移,下键实现加速,上键实现旋转,这其实都应该是函数,当然左右移动需要考虑碰撞的问题,下移需要考虑堆积和消层的问

2022-03-18 14:02:05

NOTE

这当中,有些东西是始终没变的。”“你是说,下落、旋转、碰撞判断、移动、堆积这些游戏逻辑

2022-03-18 12:26:09

NOTE

如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破

2022-03-18 12:26:26

NOTE

那么整个方块的移动其实就是数组的下标变化,比如原方块在arraySquare [3,5]上,则下移时变成arraySquare [3,6],如果下移同时还按了左键,则是arraySquare[2,6]

2022-03-18 12:26:56

NOTE

,所谓的碰撞判断,其实就是什么

2022-03-18 12:27:10

NOTE

是否能左移,就是判断arraySquare [x,y]中的x–1是否小于0,否则就撞墙了。或者arraySquare [x–1,y]是否等于1,否则就说明左侧有堆积的方块。所谓堆积,不过是判断arraySquare [x,y+1]是否等于1的过程,如果是,则将自己arraySquare [x,y]的值改1。那么消层,其实就是arraySquare [x,y]中循环x由0到9,判断arraySquare [x,y]是否都等于1,是则此行数据清零,并将其上方的数组值遍历下移一位。

2022-03-18 12:28:52

NOTE

软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离

2022-03-18 14:04:08

NOTE

如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责

2022-03-18 14:04:12

3.6 手机职责过多吗?

NOTE

垂直搜索又开始流行,这却是单一职责的思想体现

2022-03-18 14:07:02

第4章 考研求职两不误——开放-封闭原则

NOTE

你为什么不利用休息的时间考虑一下自己的简历如何写,关心一下有些什么单位在招聘呢?这样也就不至于现在这样唉声叹气

2022-03-18 14:09:42

NOTE

开放-封闭原则(The Open-Closeed Principle,简称OCP)或叫开-闭原则

2022-03-18 14:10:40

4.2 开放-封闭原则

NOTE

开放-封闭原则,是说软件实体(类、模块、函数等等)应该可以扩展,但是不可修改

2022-03-18 14:11:01

NOTE

,一个是说‘对于扩展是开放的(Open for extension)’,另一个是说‘对于更改是封闭的(Closed for modification)’

2022-03-18 14:11:45

NOTE

怎样的设计才能面对需求的改变却可以保持相对稳定,从而使得系统可以在第一个版本以后不断推出新的版本呢?

2022-03-18 14:12:55

NOTE

弹性上班工作制,早到早下班,晚到晚下班,或者每人每月允许三次迟到,迟到者当天下班补时间等等,对市场销售人员可能就更加以业绩为标准,工作时间不固定了——这其实就是对工作时间或业绩成效的修改关闭,而对时间制度扩展的开放

2022-03-18 14:14:08

4.3 何时应对变化

NOTE

无论模块是多么的‘封闭’,都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。他必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离那些变化[ASD]

2022-03-18 14:25:41

NOTE

绝不成熟的抽象和抽象本身一样重要[ASD]

2022-03-18 14:27:26

4.4 两手准备,并全力以赴

第5章 会修电脑不会修收音机?——依赖倒转原则

5.2 电话遥控修电脑

5.3 依赖倒转原则

NOTE

依赖倒转原则,原话解释是抽象不应该依赖细节,细节应该依赖于抽象,这话绕口,说白了,就是要针对接口编程,不要对实现编程

2022-03-18 14:46:12

NOTE

所以说,PC电脑硬件的发展,和面向对象思想发展是完全类似的。这也说明世间万物都是遵循某种类似的规律

2022-03-18 14:49:22

NOTE

依赖倒转原则A.高层模块不应该依赖低层模块。两个都应该依赖抽象。B.抽象不应该依赖细节。细节应该依赖抽象。[ASD]

2022-03-18 14:49:50

NOTE

我们希望能再次利用这些高层模块,但高层模块都是与低层的访问数据库绑定在一起的,没办法复用这些高层模块,这就非常糟糕了。就像刚才说的,PC里如果CPU、内存、硬盘都需要依赖具体的主板,主板一坏,所有的部件就都没用了,这显然不合理

2022-03-18 14:51:01

5.4 里氏代换原则

NOTE

里氏代换原则是Barbara Liskov女士在1988年发表的[ASD],具体的数学定义比较复杂,你可以查相关资料,它的白话翻译就是一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类对象和子类对象的区别。也就是说,在软件里面,把父类都替换成它的子类,程序的行为没有变化,简单地说,子类型必须能够替换掉它们的父类型[ASD]

2022-03-18 14:53:07

NOTE

尽管在生物学分类上,企鹅是一种鸟,但在编程世界里,企鹅不能以父类——鸟的身份出现,因为前提说所有鸟都能飞,而企鹅飞不了,所以,企鹅不能继承鸟类。

2022-03-18 14:58:24

NOTE

只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为

2022-03-18 14:57:35

NOTE

由于有里氏代换原则,才使得开放-封闭成为了可能

2022-03-18 14:58:54

5.5 修收音机

NOTE

如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之那就是过程化的设计了[ASD]

2022-03-18 14:59:28

第6章 穿什么有这么重要?——装饰模式

6.2 小菜扮靓第一版

6.3 小菜扮靓第二版

NOTE

建造者模式要求建造的过程必须是稳定的,而现在我们这个例子,建造过程是不稳定的,比如完全可以内穿西装,外套T恤,再加披风,打上领带,皮鞋外再穿上破球鞋;当然也完全可以只穿条裤衩就算完成。换句话就是说,通过服饰组合出一个有个性的人完全可以有无数种方案,并非是固定的

2022-03-18 15:16:05

6.4 装饰模式

NOTE

装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。[DP]

2022-03-18 15:16:51

NOTE

从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的

2022-03-19 12:47:06

NOTE

原来装饰模式是利用SetComponent来对对象进行包装的。这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中[DPE]

2022-03-19 12:56:39

NOTE

如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。同样道理,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类

2022-03-19 12:56:32

6.5 小菜扮靓第三版

NOTE

代码结构图

2022-03-19 12:57:10

6.6 装饰模式总结

NOTE

你起初的设计中,当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为

2022-03-19 12:58:50

NOTE

这种做法的问题在于,它们在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,就像你起初的那个‘人’类,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要

2022-03-19 12:59:06

NOTE

装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了[DP]

2022-03-19 12:59:25

NOTE

装饰模式的优点我总结下来就是,把类中的装饰功能从类中搬移去除,这样可以简化原有的类。”“是的,这样做更大的好处就是有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑

2022-03-19 12:59:49

NOTE

装饰模式的装饰顺序很重要哦,比如加密数据和过滤词汇都可以是数据持久化前的装饰功能,但若先加密了数据再用过滤功能就会出问题了,最理想的情况,是保证装饰类之间彼此独立,这样它们就可以以任意的顺序进行组合了

2022-03-19 13:00:14

第7章 为别人做嫁衣——代理模式

7.2 没有代理的代码

7.3 只有代理的代码

NOTE

他们应该都有送礼物的三个方法,只不过‘Proxy(代理)’送的礼物是‘Pursuit(追求者)’买的,实质是‘Pursuit(追求者)’送的。

2022-03-19 13:25:26

7.4 符合实际的代码

NOTE

“这下好了,娇娇不认识追求她的人,但却可以通过代理人得到礼物。效果其实是达到了

2022-03-19 13:43:36

7.5 代理模式

NOTE

代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问

2022-03-19 13:44:03

7.6 代理模式应用

NOTE

,远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实

2022-03-19 14:13:05

NOTE

虚拟代理,是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象[DP]

2022-03-19 14:15:15

NOTE

浏览器当中是用代理模式来优化下载的

2022-03-19 14:15:43

NOTE

安全代理,用来控制真实对象访问时的权限[DP]。一般用于对象应该有不同的访问权限的时候。第四种是智能指引,是指当调用真实的对象时,代理处理另外一些事[DP]

2022-03-19 14:15:57

7.7 秀才让小六代其求婚

第8章 雷锋依然在人间——工厂方法模式

8.2 简单工厂模式实现

8.3 工厂方法模式实现

8.4 简单工厂vs.工厂方法

NOTE

就等于说,我们不但对扩展开放了,对修改也开放了,这样就违背了什么原则?”“哦,是的,违背的是开放-封闭原则。

2022-03-19 14:52:09

NOTE

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类

2022-03-19 14:52:43

NOTE

既然这个工厂类与分支耦合,那么我就对它下手,根据依赖倒转原则,我们把工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。然后,所有的要生产具体类的工厂,就去实现这个接口,这样,一个简单工厂模式的工厂类,变成了一个工厂抽象接口和多个具体生成对象的工厂,于是我们要增加‘求M数的N次方’的功能时,就不需要更改原有的工厂类了,只需要增加此功能的运算类和相应的工厂类就可以了。”

2022-03-19 14:53:27

NOTE

工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。你想要加功能,本来是改工厂类的,而现在是修改客户端!

2022-03-19 14:56:47

8.5 雷锋工厂

NOTE

LeiFeng xueleifeng = new Undergraduate(); xueleifeng.BuyRice();xueleifeng.Sweep();xueleifeng.Wash();

2022-03-19 14:58:01

NOTE

这里有重复,也就有了坏味道

2022-03-19 14:59:22

NOTE

我明白了,尽管如果要换成‘社区志愿者’也还是要修改代码,但是只需要修改一处就可以了。这是最佳的

2022-03-19 15:00:31

NOTE

我感觉工厂方法克服了简单工厂违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。”“说得好,它们都是集中封装了对象的创建,使得要更换对象时,不需要做大的改动就可实现,降低了客户程序与产品对象的耦合。工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。但缺点是由于每加一个产品,就需要加一个产品工厂的类,增加了额外的开发量。”

2022-03-19 15:01:05

第9章 简历复印——原型模式

NOTE

我只是一个还没毕业的学生,哪来什么经验或工作经历,我能写什么

2022-03-19 15:04:14

NOTE

回想起来,那时候对自己手写的简历很珍惜,人家公司也很重视,收到都会认真地看并答复,哪像现在。”大鸟感慨道,“印简历就像印草纸一样,发简历更像是发广告。我听说有些公司竟然在见面会结束时以拿不了为由,扔掉所收简历就走的事情,求职者要是看到岂不气晕呀

2022-03-19 15:05:11

NOTE

简单的复制粘贴极有可能造成重复代码的灾难。我所说的意思你根本还没听懂。那就以刚才的例子,我出个需求你写写看,要求有一个简历类,必须要有姓名,可以设置性别和年龄,可以设置工作经历。最终我需要写三份简历

2022-03-19 15:06:14

9.2 简历代码初步实现

NOTE

这其实是传引用,而不是传值,这样做就如同是在b纸张和c纸张上写着简历在a处一样,没有实际的内容的

2022-03-19 15:17:23

NOTE

Clone克隆这样的方法,但怎么做不知道了。”

2022-03-19 15:17:57

9.3 原型模式

NOTE

原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。[DP]

2022-03-19 15:50:04

NOTE

对于.NET而言,那个原型抽象类Prototype是用不着的,因为克隆实在是太常用了,所以.NET在System命名空间中提供了ICloneable接口,其中就是唯一的一个方法Clone(),这样你就只需要实现这个接口就可以完成原型模式了。

2022-03-19 19:03:37

9.4 简历的原型实现

NOTE

。一般在初始化的信息不发生变化的情况下,克隆是最好的办法。这既隐藏了对象创建的细节,又对性能是大大的提高,何乐而不为呢

2022-03-19 19:06:20

9.5 浅复制与深复制

NOTE

MemberwiseClone()方法是这样,如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象

2022-03-19 19:07:10

9.6 简历的深复制实现

9.7 复制简历vs.手写求职信

第10章 考题抄错会做也白搭——模板方法模式

10.2 重复=易错+难改

10.3 提炼代码

NOTE

这还只是初步的泛化,你仔细看看,两个学生的类里面,还有没有类似的代码

2022-03-19 19:14:25

NOTE

既然用了继承,并且肯定这个继承有意义,就应该要成为子类的模板,所有重复的代码都应该要上升到父类去,而不是让每个子类都去重复

2022-03-19 19:14:54

NOTE

用模板方法模式来处理

2022-03-19 21:44:18

NOTE

我们就改动这里,增加一个虚方法

2022-03-20 15:43:17

10.4 模板方法模式

NOTE

典型的模板方法模式

2022-03-20 15:47:16

NOTE

模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

2022-03-20 15:47:27

10.5 模板方法模式特点

NOTE

模板方法模式是通过把不变行为搬移到超类,去除子类中的重复代码来体现它的优势

2022-03-20 15:50:32

10.6 主观题,看你怎么蒙

第11章 无熟人难办事?——迪米特法则

11.2 无熟人难办事

NOTE

对头(四川方言发音)

2022-03-20 16:31:17

11.3 迪米特法则

NOTE

迪米特法则(LoD)’也叫最少知识原则。[J&DP]

2022-03-20 16:31:36

NOTE

迪米特法则(LoD),如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。[J&DP]

2022-03-20 16:31:56

NOTE

首先强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限[J&DP],也就是说,一个类包装好自己的private状态,不需要让别的类知道的字段或行为就不要公开

2022-03-20 16:32:13

NOTE

需要公开的字段,通常就用属性来体现了。这不是封装的思想吗?

2022-03-20 16:32:24

NOTE

类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。也就是说,信息的隐藏促进了软件的复用

2022-03-20 16:32:58

第12章 牛市股票还会亏钱?——外观模式

NOTE

众多投资者对众多股票的联系太多,反而不利于操作,这在软件中是不是就称为耦合性过高。而有了基金以后,变成众多用户只和基金打交道,关心基金的上涨和下跌就可以了,而实际上的操作却是基金经理人在与上千支股票和其他投资产品打交道

2022-03-20 16:33:54

12.2 股民炒股代码

NOTE

具体股票、国债、房产类

2022-03-20 16:34:32

12.3 投资基金代码

12.4 外观模式

NOTE

外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。[DP]

2022-03-20 16:35:13

NOTE

它完美地体现了依赖倒转原则和迪米特法则的思想,所以是非常常用的模式之一

2022-03-20 16:37:56

12.5 何时使用外观模式

NOTE

段来说,首先,在设计初期阶段,应该要有意识的将不同的两个层分离,比如经典的三层架构,就需要考虑在数据访问层和业务逻辑层、业务逻辑层和表示层的层与层之间建立外观Facade,这样可以为复杂的子系统提供一个简单的接口,使得耦合大大降低。其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,大多数的模式使用时也都会产生很多很小的类,这本是好事,但也给外部调用它们的用户程序带来了使用上的困难,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖。第三,在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含非常重要的功能,新的需求开发必须要依赖于它。此时用外观模式Facade也是非常合适的。你可以为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。[R2P

2022-03-20 16:38:43

第13章 好菜每回味不同——建造者模式

NOTE

依赖倒转原则?抽象不应该依赖细节,细节应该依赖于抽象

2022-03-20 16:41:23

NOTE

由于我们要吃的菜都依赖于厨师这样的细节,所以我们就很被动

2022-03-20 16:41:28

NOTE

工作流程也是细节

2022-03-20 16:55:24

NOTE

这里工作流程可以是一种抽象的流程,具体放什么配料、烤多长时间等细节依赖于这个抽象

2022-03-20 16:55:35

13.2 建造小人一

13.3 建造小人二

NOTE

最好的办法是规定,凡是建造小人,都必须要有头和身体,以及两手两脚

2022-03-20 17:07:44

13.4 建造者模式

NOTE

建造者模式(Builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。[DP]

2022-03-20 17:09:55

NOTE

然后,我们需要建造一个瘦的小人,则让这个瘦子类去继承这个抽象类,那就必须去重写这些抽象方法了。否则编译器也不让你通过。

2022-03-20 17:11:16

NOTE

我们还缺建造者模式中一个很重要的类,指挥者(Director),用它来控制建造过程,也用它来隔离用户与建造过程的关联

2022-03-20 17:15:50

NOTE

如果这些细节是每个具体的小人都需要构建的,那就应该要加进去,反之,就没必要。其实建造者模式是逐步建造产品的,所以建造者的Builder类里的那些建造方法必须要足够普遍,以便为各种类型的具体建造者构造

2022-03-20 17:26:47

13.5 建造者模式解析

13.6 建造者模式基本代码

NOTE

建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时适用的模式

2022-03-20 17:36:33

第14章 老板回来,我不知道——观察者模式

NOTE

生气却不发作,很牛

2022-03-20 17:43:12

14.2 双向耦合的代码

NOTE

首先开放-封闭原则,修改原有代码就说明设计不够好。其次是依赖倒转原则,我们应该让程序都依赖抽象,而不是相互依赖。OK,我去改改,应该不难的

2022-03-21 00:09:47

14.3 解耦实践一

NOTE

对呀,你想想看,你们公司最后一次,你们的老板回来,前台来不及电话了,于是通知大家的任务变成谁来做?”“是老板,对的,其实老板也好,前台也好,都是具体的通知者,这里观察者也不应该依赖具体的实现,而是一个抽象的通知者。”

2022-03-21 00:13:45

14.4 解耦实践二

14.5 观察者模式

NOTE

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

2022-03-21 00:14:45

14.6 观察者模式特点

14.7 观察者模式的不足

14.8 事件委托实现

14.9 事件委托说明

14.10 石守吉失手机后的委托

第15章 就不能不换DB吗?——抽象工厂模式

NOTE

“只要网站要维护,比如修改或增加一些功能,你就得改两个项目吧,至少在数据库中做改动,相应的程序代码都要改,甚至和数据库不相干的代码也要改,你既然有两个不同的版本,两倍的工作量也是必然的。”

2022-06-15 19:35:28

15.2 最基本的数据访问程序

15.3 用了工厂方法模式的数据访问程序

NOTE

此时由于多态的关系,使得声明IUser接口的对象iu事先根本不知道是在访问哪个数据库,却可以在运行时很好地完成工作,这就是所谓的业务逻辑与数据访问的解耦。

2022-04-01 00:03:40

NOTE

多写些类有什么关系,只要能增加灵活性,以后就不用加班了。小菜好好加油

2022-04-01 00:04:05

15.4 用了抽象工厂模式的数据访问程序

NOTE

“只有一个User类和User操作类的时候,是只需要工厂方法模式的,但现在显然你数据库中有很多的表,而SQL Server与Access又是两大不同的分类,所以解决这种涉及到多个产品系列的问题,有一个专门的工厂模式叫抽象工厂模式。

2022-04-01 01:51:09

15.5 抽象工厂模式

15.6 抽象工厂模式的优点与缺点

15.7 用简单工厂来改进抽象工厂

15.8 用反射+抽象工厂的数据访问程序

15.9 用反射+配置文件实现数据访问程序

15.10 无痴迷,不成功

第16章 无尽加班何时休——状态模式

NOTE

上午状态好,中午想睡觉,下午渐恢复,加班苦煎熬

2022-03-21 00:17:41

16.2 工作状态-函数版

16.3 工作状态-分类版

16.4 方法过长是坏味道

NOTE

“仔细看看,MartinFowler曾在《重构》中写过一个很重要的代码坏味道,叫做‘Long Method’,方法如果过长其实极有可能是有坏味道了。”

2022-03-21 00:18:52

NOTE

“你要知道,你这个方法很长,而且有很多的判断分支,这也就意味着它的责任过大了。无论是任何状态,都需要通过它来改变,这实际上是很糟糕的。

2022-03-21 00:19:12

NOTE

把这些分支想办法变成一个又一个的类,增加时不会影响其他类。然后状态的变化在各自的类中完成。”小菜说道,“理论讲讲很容易,但实际如何做,我想不出来。”

2022-03-21 00:19:37

NOTE

GoF已经为我们针对这类问题提供了解决方案,那就是‘状态模式’。

2022-03-21 00:19:43

16.5 状态模式

NOTE

状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

2022-03-21 00:19:49

NOTE

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化

2022-03-21 00:20:02

16.6 状态模式好处与用处

NOTE

状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来[DP]

2022-03-21 00:21:25

NOTE

是不是就是将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换[DP]。”“说白了,这样做的目的就是为了消除庞大的条件分支语句

2022-03-21 00:22:18

16.7 工作状态-状态模式版

第17章 在NBA我需要翻译——适配器模式

17.2 适配器模式

NOTE

适配器模式(Adapter),将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。[DP]

2022-03-21 00:24:14

NOTE

有些国家用110 V电压,而我们国家用的是220 V,但我们的电器,比如笔记本电脑是不能什么电压都能用的,但国家不同,电压可能不相同也是事实,于是就用一个电源适配器,只要是电,不管多少伏,都能把电源变成需要的电压,这就是电源适配器的作用。适配器的意思就是使得一个东西适合另一个东西的东西

2022-03-21 00:24:38

NOTE

系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况

2022-03-21 00:24:47

NOTE

GoF的设计模式中,对适配器模式讲了两种类型,类适配器模式和对象适配器模式,由于类适配器模式通过多重继承对一个接口与另一个接口进行匹配,而C#、VB.NET、JAVA等语言都不支持多重继承(C++支持),也就是一个类只有一个父类,所以我们这里主要讲的是对象适配器

2022-03-21 00:24:58

17.3 何时使用适配器模式

17.4 篮球翻译适配器

17.5 适配器模式的.NET应用

17.6 扁鹊的医术

第18章 如果再回到从前——备忘录模式

18.2 游戏存进度

NOTE

代码无错未必优

2022-03-21 00:28:19

NOTE

因为这样写就把整个游戏角色的细节暴露给了客户端,你的客户端的职责就太大了,需要知道游戏角色的生命力、攻击力、防御力这些细节,还要对它进行‘备份’。以后需要增加新的数据,例如增加‘魔法力’或修改现有的某种力,例如‘生命力’改为‘经验值’,这部分就一定要修改了

2022-03-21 00:28:42

18.3 备忘录模式

NOTE

备忘录(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

2022-03-21 00:29:04

18.4 备忘录模式基本代码

NOTE

Memento模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。

2022-03-21 00:31:56

18.5 游戏进度备忘

第19章 分公司=一部门——组合模式

19.2 组合模式

19.3 透明方式与安全方式

NOTE

为什么Leaf类当中也有Add和Remove,树叶不是不可以再长分枝吗

2022-03-21 00:33:17

NOTE

透明方式,也就是说在Component中声明所有用来管理子对象的方法,其中包括Add、Remove等。这样实现Component接口的所有子类都具备了Add和Remove。这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备Add()、Remove()方法的功能,所以实现它是没有意义的。

2022-03-21 00:33:29

19.4 何时使用组合模式

19.5 公司管理系统

19.6 组合模式好处

第20章 想走?可以!先买票——迭代器模式

20.2 迭代器模式

NOTE

迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。[DP]

2022-03-21 11:30:53

20.3 迭代器实现

NOTE

当你需要对聚集有多种方式遍历时,可以考虑用迭代器模式

2022-03-21 11:36:17

20.4 .NET的迭代器实现

NOTE

非泛型集合

2022-03-21 12:37:53

NOTE

迭代器(Iterator)模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据

2022-03-21 12:41:24

20.5 迭代高手

第21章 有些类也需计划生育——单例模式

21.2 判断对象是否是null

NOTE

如果做任何事情不求完美,只求简单达成目标,那你又如何能有提高。

2022-03-21 12:42:36

NOTE

复制粘贴是最容易的编程,但也是最没有价值的编程。你现在将两个地方的代码复制在一起,这就是重复。这要是需求变化或有Bug时就需要改多个地方。

2022-03-21 12:43:05

21.3 生还是不生是自己的责任

21.4 单例模式

NOTE

单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。[DP]

2022-03-21 12:47:41

NOTE

,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。[DP]

2022-03-21 12:48:00

NOTE

实用类通常也会采用私有化的构造方法来避免其有实例。但它们还是有很多不同的,比如实用类不保存状态,仅提供一些静态方法或静态属性让你使用,而单例类是有状态的。实用类不能用于继承多态,而单例虽然实例唯一,却是可以有子类来继承。实用类只不过是一些方法属性的集合,而单例却是有着唯一的对象实例。在运用中还得仔细分析再作决定用哪一种方式

2022-03-21 13:03:31

21.5 多线程时的单例

21.6 双重锁定

21.7 静态初始化

第22章 手机软件何时统一——桥接模式

22.2 紧耦合的程序演化

NOTE

[DPE]’但事实上,很多情况用继承会带来麻烦。比如,对象的继承关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性[DP]

2022-03-21 13:18:00

NOTE

在面向对象设计中,我们还有一个很重要的设计原则,那就是合成/聚合复用原则。即优先使用对象合成/聚合,而不是类继承[DP]

2022-03-21 13:18:12

22.3 合成/聚合复用原则

NOTE

合成/聚合复用原则(CARP),尽量使用合成/聚合,尽量不要使用类继承。[J&DP

2022-03-21 13:20:53

NOTE

优先使用对象的合成/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物[DP]。

2022-03-21 13:21:13

22.4 松耦合的程序

22.5 桥接模式

NOTE

桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们都可以独立地变化。[DP]

2022-03-21 13:21:29

NOTE

就是让‘手机’既可以按照品牌来分类,也可以按照功能来分类。

2022-03-21 13:21:58

NOTE

桥接模式的核心意图就是把这些实现独立出来,让它们各自地变化。这就使得每种实现的变化不会影响其他实现,从而达到应对变化的目的。

2022-03-21 13:22:10

22.6 桥接模式基本代码

NOTE

那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合

2022-03-21 13:46:42

22.7 我要开发“好”游戏

第23章 烤羊肉串引来的思考——命令模式

23.2 烧烤摊vs.烧烤店

23.3 紧耦合设计

23.4 松耦合设计

23.5 松耦合后

23.6 命令模式

23.7 命令模式作用

第24章 加薪非要老总批?——职责链模式

24.2 加薪代码初步

24.3 职责链模式

24.4 职责链的好处

NOTE

接收者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用

2022-06-15 09:33:27

24.5 加薪代码重构

24.6 加薪成功

第25章 世界需要和平——中介者模式

NOTE

尽管将一个系统分割成许多对象通常可以增加其可复用性,但是对象间相互连接的激增又会降低其可复用性了。你知道为什么会这样?”“我想是因为大量的连接使得一个对象不可能在没有其他对象的支持下工作,系统表现为一个不可分割的整体,所以,对系统的行为进行任何较大的改动就十分困难了

2022-03-21 14:15:20

NOTE

国与国之间完全可以通过‘联合国’这个中介者来发生关系,而不用直接通信

2022-03-21 14:15:36

25.2 中介者模式

25.3 安理会做中介

25.4 中介者模式优缺点

第26章 项目多也别傻做——享元模式

26.2 享元模式

NOTE

享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。[DP]

2022-03-21 14:20:11

26.3 网站共享代码

26.4 内部状态与外部状态

26.5 享元模式应用

第27章 其实你不懂老板的心——解释器模式

27.2 解释器模式

NOTE

如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题[DP]。比方说,我们常常会在字符串中搜索匹配的字符或判断一个字符串是否符合我们规定的格式,此时一般我们会用什么技术?

2022-03-21 14:22:24

27.3 解释器模式好处

27.4 音乐解释器

27.5 音乐解释器实现

27.6 料事如神

第28章 男人和女人——访问者模式

NOTE

没有事业的成功,你找出再多的男女差异也找不到女朋友的。还是好好学习吧

2022-03-21 14:37:56

28.2 最简单的编程实现

NOTE

你至少要分析一下,这里面有没有类可以提炼,有没有方法可以共享什么的

2022-03-21 14:39:49

28.3 简单的面向对象实现

28.4 用了模式的实现

NOTE

双分派的技术,首先在客户程序中将具体状态作为参数传递给“男人”类完成了一次分派,然后“男人”类调用作为参数的“具体状态”中的方法“男人反应”,同时将自己(this)作为参数传递进去。这便完成了第二次分派

2022-03-21 14:50:21

NOTE

‘接受’方法就是一个双分派的操作,它得到执行的操作不仅决定于‘状态’类的具体状态,还决定于它访问的‘人’的类别。”

2022-03-21 14:50:27

28.5 访问者模式

28.6 访问者模式基本代码

28.7 比上不足,比下有余

第29章 OOTV杯超级模式大赛——模式总结

29.2 报名参赛

29.3 超模大赛开幕式

29.4 创建型模式比赛

29.5 结构型模式比赛

29.6 行为型模式一组比赛

NOTE

主要原因是这次是设计模式比赛,而MVC是多种模式的综合应用,应该算是一种架构模式,所以被排除在外

2022-06-15 09:17:50

29.7 行为型模式二组比赛

29.8 决赛

29.9 梦醒时分

29.10 没有结束的结尾

读者意见反馈表

附录A 培训实习生——面向对象基础

A.1 培训实习生

A.2 类与实例

A.3 构造方法

A.4 方法重载

A.5 属性与修饰符

A.6 封装

A.7 继承

A.8 多态

A.9 重构

A.10 抽象类

A.11 接口

A.12 集合

A.13 泛型

A.14 委托与事件

A.15 客套

附录B 参考文献