[BLOG]设计模式之禅 读书笔记 02-09-2011更新
>>一本好书等于无尽的联想<font color=brown>前不久,一位孤居海外的死党跌跌撞撞闯过重重安检回到国内,希望我推荐一本
算法设计的入门书籍给他,认真说来,我自己都不太懂什么算法设计,属于土八路,
哪里知道什么正规军用的家伙,可是,盛情难却,只好突击泡书城,好在影印书籍并
不太多,几个回合下来就相中了哪本《The Algorithm Design Manual》,翻了翻,
的确是好书,不觉赞叹:“果然是好书,若不是送礼,我一定去下载电子版”。
悻悻正欲离去,一眼瞟到了一本神作《设计模式之禅》,打开一看,顿时金光四
射,闪得我睁不开眼睛……果然是神作啊……立马看看背面……痛下决心,还是当当
上买吧……好歹7折……
于是,本贴读书笔记就此开始……
P.S 看了这本书,一个嵌入式系统软件设计师书目浮现在我的脑海里(修订讨论稿):
入门阶段:任意单片机入门书籍
思考阶段:基于时间触发的嵌入式系统设计(忘记哪个出版社了)
基础阶段:《UML + OOPC嵌入式C语言开发精讲》(电子工业出版社)
基础提升:《设计模式之禅》(机械工业出版社)
理论入门:《自动机理论与应用》(英文名称《Automata, Computability, and
Complexity Theory and Application》清华大学出版社)
理论提升:《The Algorithm Design Manaual》(清华大学出版社)
应用阶段:《操作系统》(《Operating System》 3rd Edition 机械工业出版社)
构架阶段:《编译器构造C语言描述》(机械工业出版社)
... Part1 大旗不挥,谁敢冲锋——6大设计原则全新解读
这是全书的开篇,从标题上就看出作者“霸气外露”,至少是一个老_江湖,也许
还是一个研发总监之类的角色;仔细看来,全部六个章节一次介绍了面向对象软件设
计的基本6个基本原则……我了个去的,可算找到组织了……草草一看,果然简单易
懂不仅让我有很多共鸣,也立竿见影的解决了我很多的疑问……
<font color=blue>第一章 单一职责原则
这一章介绍了一个叫做SPR(Single Responsibility Principle)的原则,
翻译成中文也就是“单一职责原则”,其定义如下:
There should never be more than one reason for a class to change.
(“应该”有且仅有一种原因引起类的变更)
这个原则有三个看点,一个是“类”,一个是“有且仅有一个原因”最后
一个,也是最关键的是“应该”(should)而不是必须(must)。简单说,就
是类写好以后,在未来扩展和修改的时候,最好只有一种原因会导致这个类必
须被扩展和修改——这当然是因为我们希望修改的工作量和牵扯的其他修改最
小最少。
为了实现这个目标,最好的办法自然就是给一个类赋予为一个的一个职责,
这样当且仅当实现这个职责的方法或者相关的属性需要更新的时候,才会去修
改这个类,而且不会牵连无辜的人。
书中说,所谓的单一职责愿望是好的,却非常难以做到,原因是,怎样算
职责?换句话说,如何划分功能——程序员觉得那些功能属于某一个职责,这
个在理解上就是飘忽不定的。既然职责是飘忽不定的,那么相关的“引起修改”
的原因自然也就是变化不定的……所以……单一职责很多情况下只能是一种自
我约束——除非在某种情况下,团队或者我们自己对职责有明确的定义。
书中给出结论说:
单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来
衡量接口或者类设计是否优良,但是“职责”和“变化原因”都是不可度量的,
因项目而异,因环境而异。<>
因此,作者的建议是:
接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。
关于单一职责在东方和西方文化理解的差异上,作者给出了一个比喻,他
说,东方人的筷子可以有多个职责:可以分食物,可以送食物到嘴里(傻孩子:
貌似还可以行酒令),而西方让,刀是刀,叉是叉,各司其职,单一职责。这
就是文化差异……吃饭尚且如此,更何况是开发软件呢……(傻孩子:^_^)
第二章 里氏替换原则
所谓里氏替换原则(Liskov Substitution Principle 简称LSP)是一个
规范面向对象编成中我们是用“继承”特性时所需要遵守的原则。里氏替换原
则有两种定义:
Definition A: If for each object o1 of type S there is an object
o2 of type T such that for all programs P defined in terms of T, the
behavior of P is unchanged when o1 is substituted for o2 when S is a
subtype of T.
挺难懂的一种E文描述……太TMD的专业了……,另外一种就要直接的多:
Definition B: Functions that use pointers of references to base
classes must be able to use objects of derived classes without
knowing it(所有引用基类的地方必须能够透明的使用其子类的对象)
这种定义至少字面上的意思还是容易理解的:简单说,就是老爹干的活,
儿子必须干的一样好;儿子干的活,老爹未必能胜任。
LSP实际上是对我们一种习惯性的开发方式作出了具体的指导,并且这种
指导原则可以保证我们的代码在未来扩充的同时,不会影响以往的功能。这种
开发方式就是,将一系列未来可能被扩展的类,抽象出接口或者抽象类,并为
这些接口或者类编写对应的方法和属性;这样无论接口或者类会被派生成什么
样子,对于我们事先编写的方法和属性来说,都是一视同仁的。如何保证扩展
后子类仍然保留父类的特性呢?里氏替换原则就是一个不错的评判标准。
根据里氏原则,书中给出了两个推论:
推论1:覆盖(Override)或实现(Implement)父类的方法时输入参数
(的类型)可以被放大;(我理解为:要比老爹强)
推论2:覆写(Override)或实现(Implement)父类的方法时输出结果
(的类型)可以被缩小;(我理解为:要比老爹更精准)
在实践中,作者提到了一种最佳实践该理论的方式:在项目中,采用里氏
替换原则时,尽量避免子类的“个性”,一旦子类有“个性”,这个子类和
父类之间的关系就很难调和了(傻孩子:难道是代沟……),把子类当作父类
用,子类的“个性”被抹杀——委屈了点;把子类单独作为一个业务来使用,
则会让代码间的耦合关系变得扑朔迷离——缺乏类替换的标准。
第三章 依赖倒置原则
所谓的依赖倒置原则(Dependence Inversion Principle,简称DIP),说
白了就是“基于接口的开发原则”,要点如下:
a. 高层模块不应该依赖低层模块,两者都应该依赖其抽象;
b. 抽象不应该依赖细节;
c. 细节应该依赖抽象;
通俗的说,如果我们要面向的(要开发的)对象存在扩展的可能,那么我们
应该首先建立一个抽象类,该抽象类包含了这类对象的最基本操作方法和属性;
同时,最好为这个抽象类在建立一个或多个接口,以在一定范围内满足单一职责
原则以及进一步提高该抽象类的对外功能输出能力。
依赖倒置原则的本质就是通过抽象(接口或者抽象类)使各个类或者模块的
实现彼此独立,互不影响,实现模块间的松耦合,我们只要做到以下几点,就可
以实现这一原则:
1、每个类尽量都有接口或者抽象类,或者抽象类和接口类都具有;
2、变量的表面类型尽量是接口或者是抽象类;
3、任何类都不应该从具体类派生;
4、尽量不要覆写基类的方法;
5、结合里氏替换原则使用
最后,作者强调了一点:依赖倒置原则的优点在小型项目中很难体现出来,
比如小于10人月的项目;但是在一个大型项目中,采用依赖倒置原则有非常多的
优点,特别是规避一些非技术因素引起的问题。项目越大,需求变化的概率也越
大,通过采用依赖倒置原则设计的接口或者抽象泪对实现类进行约束,可以减少
需求因其变化的工作量剧增的情况。
第四章 接口隔离原则
第五章 迪米特法则
第六章 开闭原则 Part 2 真刀真枪——23种设计模式完美演绎<font color=brown>
读完了,忘记整理了…… - -b Part 3 谁的地盘谁做主——设计模式PK<font color=brown>
读完了,忘记整理了…… - -b 占位 广告位,出租ing 跟着学习 不错。呵呵。我觉得应该在论坛里面多介绍一些好书,多来一些读书笔记。呵呵。我也很喜欢阅读。最近正在看一个同龄人写的<Boost程序库完全开发指南>,还不错,至少系统的让我了解到Boost的大概情况。Boost方面的书非常少,看英文的文献太吃力,又很难坚持。以前对Boost了解不多,只知道他是好东西,经过这本书了,我开始尝试把Boost里面的一些不错的组件应用到自己的软件开发里面去。 感觉这本书和下面这本由类似的地方:
您的设计模式ourdev_608212AYXX91.pdf(文件大小:3.01M) (原文件名:设计模式之禅.pdf)
书的原名您的设计模式 顶楼主,搬个板凳学习 对此类书籍已经没什么兴趣了。 《The Algorithm Design Manual》电子版
点击此处下载 ourdev_608219M6O9RG.pdf(文件大小:10.92M) (原文件名:The Algorithm Design Manual.pdf) mark 时间触发嵌入式系统设计模式 Michael J. Pont著 周敏译 这本书是 电力出版社 的
这本书700多页的厚度对初学者来书太长了。
这本书的作者还有一本讲c语言的书,C语言嵌入式系统开发 ,200多页,比较适合刚开始学习的人,里面也有一些合作式调度的内容。 学习 回复【11楼】wenfeiexe
-----------------------------------------------------------------------
呵呵,下载看看。 mark 果断围观!! 回复【13楼】flagyan
-----------------------------------------------------------------------
时间触发嵌入式系统设计模式 是我写代码的圣经,用它办法写出上万行代码,非常稳定。
呵呵,时间触发嵌入式系统设计模式 这本书几乎被我翻烂了,已经脱页了。 回复【18楼】fickle
-----------------------------------------------------------------------
这本书是好书。
我的意思是 入门阶段 丢这么一本厚书过去会把人吓跑的。 学习了。 学习了。 mark to 【19楼】 flagyan
这样一本书就吓跑了……估计读书习惯不好……也不用看以后的书了……
to 【10楼】 aleyn 煮茶村长
你是过来人了……当然没有兴趣了……就好比我现在不会继续去研究C语言指针一样的 Mark一个,还是跟了很多资源么,下班回家下下来,放到Kindle上 好贴 记得大二的时候看 高焕堂的《UML + OOPC嵌入式C语言开发精讲》前面才看到第二页就因为看不懂里面的C中Class那个东西 下不去了, 于是继续回去写觉得的程序,看简单的书
时间触发嵌入式系统设计模式这本书我总是推荐给身边学51单片机的人. 蛮好的书. 好贴 , Mark一个` to 【27楼】 QQ373466062 萤火虫
如果你现在能看懂C实现class,推荐你还是要看一看那本书。 MARK mark! mark支持 读书提升,mark! 支持楼主 强贴留名 回复【27楼】QQ373466062 萤火虫
记得大二的时候看 高焕堂的《uml + oopc嵌入式c语言开发精讲》前面才看到第二页就因为看不懂里面的c中class那个东西 下不去了, 于是继续回去写觉得的程序,看简单的书
时间触发嵌入式系统设计模式这本书我总是推荐给身边学51单片机的人. 蛮好的书.
-----------------------------------------------------------------------
"这本书我总是推荐给身边学51单片机的人",
一直把时间模式用在32bit的芯片里。以为开篇那个,医生照顾病人的例子很形象,因此固执认为时间模式是嵌入式最佳拍档。
可是,有一点实在想不懂,为什么每个厂家总是拿中断响应速度说事? 收藏一下 果断马克。 记号图书 先标记。 我也正在看这本书~标记一下~ 好书标记 回去研究一下 注定是个强帖! mark 回复【18楼】fickle
时间触发嵌入式系统设计模式 是我写代码的圣经,用它办法写出上万行代码,非常稳定。
--------------------------------------------------------------------------------
也翻过这本书,但是里面只允许开一个定时器中断,不理解那其它的中断该怎么处理?例如通讯,ADC等等 持续关注!
学习 傻孩子能不能推荐下学习C++的经典书籍呢? mark 下了 C++的书我读的很少……不好意思……给不出什么好的建议……
不过论坛的其他人应该可以给出答案吧? 强帖留名 跟着大家一起学习 mark 回复【46楼】pujing
回复【18楼】fickle
时间触发嵌入式系统设计模式 是我写代码的圣经,用它办法写出上万行代码,非常稳定。
--------------------------------------------------------------------------------
也翻过这本书,但是里面只允许开一个定时器中断,不理解那其它的中断该怎么处理?例如通讯,adc等等
-----------------------------------------------------------------------
对,只开一个中断(一般1ms,称为1 tick),其他功能模块都写成switch-case-break形式且(每个case满足1ms内执行完),分别在不
同的tick下执行。
呵呵,Gorgon Meducer 帅哥早已论述,详细还是看他的帖子吧。 时间触发嵌入式系统设计模式 mark MARK cool 跟着Gorgon Meducer 帅哥学习啊! mark!~ 标记一下 现在已经是2011年了 标题是不是该改一下啊 呵呵 强烈MARK hehe,应该是楼主的笔误阿
我也比较感觉好像还在10年呢,这一年动荡太多太多了,,,11年认真对付状态机
傻老师的侧重点是对的,很多单片机级别的程序,无非就是状态机变来变去,中断触发,如何处理多个中断,等等
去年开始实际操练状态机,很多关于状态机的资料,都很匮乏,而至如rtos的东东却是很多,但实际操作却意义不大,
以我知道的前辈的讲_法,,单片机最复杂,到头也就是这个状态机,什么rtos之类的,离商业和产品还差的远呢
前辈做完下位机之后,发现什么数据库,应用层,都没有下位机这么难。当然是不用c++的前提。 好贴,学习! 学习了。 好贴,跟着学。 jh jh 记号 MARK.....最喜欢有人推荐好书了。
希望都能下载到,呵呵。。。。。 想在此贴留点什么,
但是打开几次却又只有默默关上!
现在连class的真正含义都没有明白,更不用说用C 融合class的编程思想。
希望自己的功力有一天能达到这个层次,
一个嵌入式业余爱好者的迷茫…… 关注 to 【76楼】 chengyang79
如果你没有搞清楚类是什么东西,不要紧。你尝试在做模块化的时候,用结构体描述这个模块
所需的全部全局变量,再狠一点,连这个模块所有的操作函数都用函数指针来指向,并把函数指针
保存在结构体里面……
做完这两步,然后多用,多体会,然后学会简化……然后再去看所谓的class。
to 【68楼】 reloaded 电子浪人
惭愧,果然写错了……
状态机思想是计算机理论之根本……运用好了,没有啥搞不定的应用程序……(包括PC) 顶。。。。。mark 围观…… mark 围观一下。 留脚印 mark 这个这个很值得关注 回复【78楼】Gorgon Meducer傻孩子
to 【68楼】 reloaded 电子浪人
惭愧,果然写错了……
状态机思想是计算机理论之根本……运用好了,没有啥搞不定的应用程序……(包括pc)
-----------------------------------------------------------------------
我还特地装了iar的visualstate了呢,结果一看范例,好夸张啊,全uml框图 ,
实在用不上真实场合
还得靠笔头画画流程 那是你不习惯用UML,其实我也不习惯用UML,不过我都是打腹稿,就和珠心算类似。真的习惯了用全状态机以后,基本也是不需要画图的,不过这应该不是好习惯哈。 学习,呵呵 论坛里好东西真多 标记 mark visualState 狠下心学学还是很方便的!
刚开始让它生成readable代码,边画图边对代码就好理解了,
不过它的状态机代码思路和平时搞FPGA的不一样。
现在单片机资源多,确实可以放开手去搞架构设计了。 傻孩子大哥能推荐一些C函数指针方面的书吗?我一遇到C函数指针就有点晕。如下面:
typedef struct _USER_STANDARD_REQUESTS
{
void (*User_GetConfiguration)(void); /* Get Configuration */
void (*User_SetConfiguration)(void); /* Set Configuration */
void (*User_GetInterface)(void); /* Get Interface */
void (*User_SetInterface)(void); /* Set Interface */
void (*User_GetStatus)(void); /* Get Status */
void (*User_ClearFeature)(void); /* Clear Feature */
void (*User_SetEndPointFeature)(void); /* Set Endpoint Feature */
void (*User_SetDeviceFeature)(void); /* Set Device Feature */
void (*User_SetDeviceAddress)(void); /* Set Device Address */
}
USER_STANDARD_REQUESTS; 没搞明白luminary的图形库里的函数输入参数里都有一个指针有什么用,请教?
//*****************************************************************************
//
//! This structure defines the characteristics of a display driver.
//
//*****************************************************************************
typedef struct
{
//
//! The size of this structure.
//
long lSize;
//
//! A pointer to display driver-specific data.
//
void *pvDisplayData;
//
//! The width of this display.
//
unsigned short usWidth;
//
//! The height of this display.
//
unsigned short usHeight;
//
//! A pointer to the function to draw a pixel on this display.
//
void (*pfnPixelDraw)(void *pvDisplayData, long lX, long lY,
unsigned long ulValue);
//
//! A pointer to the function to draw multiple pixels on this display.
//
void (*pfnPixelDrawMultiple)(void *pvDisplayData, long lX, long lY,
long lX0, long lCount, long lBPP,
const unsigned char *pucData,
const unsigned char *pucPalette);
//
//! A pointer to the function to draw a horizontal line on this display.
//
void (*pfnLineDrawH)(void *pvDisplayData, long lX1, long lX2, long lY,
unsigned long ulValue);
//
//! A pointer to the function to draw a vertical line on this display.
//
void (*pfnLineDrawV)(void *pvDisplayData, long lX, long lY1, long lY2,
unsigned long ulValue);
//
//! A pointer to the function to draw a filled rectangle on this display.
//
void (*pfnRectFill)(void *pvDisplayData, const tRectangle *pRect,
unsigned long ulValue);
//
//! A pointer to the function to translate 24-bit RGB colors to
//! display-specific colors.
//
unsigned long (*pfnColorTranslate)(void *pvDisplayData,
unsigned long ulValue);
//
//! A pointer to the function to flush any cached drawing operations on
//! this display.
//
void (*pfnFlush)(void *pvDisplayData);
}
tDisplay;
每个函数里都有void *pvDisplayData的输入参数但是又没有用到。 mark to 【94楼】 McuY
这实际上不是一个单纯的结构题,而是一个抽象类(也可以理解为
接口):
结构体变量是属性;而所有的函数指针实际上抽象方法;你有兴趣
可以去找一本叫做OOC的书,或者中国人写的OOPC的书看看,就知道啦。
面向对象的出发点就是:将要数据和处理数据的方法封装在一起,
就是面向对象。从这一点出发,上面的结构体就是一个类。 to 【93楼】 wjian10
函数指针如果那样写,当然会晕,所以我一直提倡另外一种写法,
以下内容是与你写的内容等效的,看了你就不觉得晕了:
//! \brief 我们首先定义了一个函数原型
typedef void USER_FUNC(void);
//! \brief 然后用函数原型定义结构体成员
//! @{
typedef struct _USER_STANDARD_REQUESTS
{
USER_FUNC *User_GetConfiguration; //!< Get Configuration
USER_FUNC *User_SetConfiguration; //!< Set Configuration
...
USER_FUNC *User_SetDeviceAddress; //!< Set Device Address
} USER_STANDARD_REQUESTS;
//! @} mark一下,得慢慢看。 学习 牛人呀~~!学习了!! 这个这个很值得关注做个标记 mark mark mark
从“基础阶段”开始吧... mark
页:
[1]
2