- 浏览: 2470349 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (574)
- Book (62)
- Architecture (6)
- Java (39)
- Taobao (41)
- Distributed (4)
- Life (72)
- Database (7)
- Spring (16)
- Photography (15)
- Bicycle (41)
- Test (20)
- jBPM (8)
- Business (12)
- Movie (3)
- Ajax (15)
- Code (7)
- Eclipse (96)
- VIM (2)
- Music (6)
- Groovy (10)
- AutoHotKey (3)
- Dorado (10)
- Maven (7)
- Scrum (5)
- English (20)
- Financial (12)
- OSGi (3)
- Other (4)
- Tool (6)
- Browser (1)
- PPT (1)
- Project Management (4)
- Agile (6)
- Nosql (1)
- Search engine (6)
- Shell (2)
- Open Source (4)
- Storm (10)
- Guava (3)
- Baby (1)
- netty (1)
- Algorithm (1)
- Linux (1)
- Python (2)
最新评论
-
roy2011a:
https://github.com/ebottabi/sto ...
storm的序列化问题及与spring的结合方式 -
roy2011a:
能抗能打 写道哥们儿,你好!能共享下那个storm与sprin ...
storm的序列化问题及与spring的结合方式 -
Alick1:
兄弟,你之前是不是在深圳的正阳公司呆过啊?
storm的ack和fail -
liuleixwd:
先点个赞,写的非常好!有个问题请教下,如果我再bolt里不用e ...
storm的ack和fail -
yao-dd:
solr的facet查询
这是一本关注程序细节并具有浓厚实战意义的书籍, 它主要是来告诉我们如何写出容易让人理解的代码. 如果非要在书名前加一个限定词的话, "java实现模式"可能更贴切一些, 因为里面的代码都是以java作为例子来说明的. 作者是junit的贡献者之一, 因此里面的很多例子都是从junit中来的.
这本书也解决了很多自己在实际开发中的一些抉择困惑. 是一本非常值得常看的书籍. 另外翻译的也非常不错, 不像有些书让人看了云里雾里的, 不知所云.
本书按照方法, 行为, 类, 状态, 集合, 框架的顺序依次对相关的实现模式加以说明来阐述如何写出好的代码. 也是本书的重点, 集合主要是在讲java.util下的集合类的使用法则, 框架部分主要是框架的开发有自己的规则, 围绕兼容性, 扩展性方面在说事儿, 没怎么看明白, 可以略过^_^
价值观
沟通, 简单, 灵活(也是实现模式的三个价值观)影响了我在编程时所作的每个决策
价值观有普遍的意思, 但是很难直接使用, 模式虽然可以直接是使用, 但是却针对具体的场景, 原则在二者之间搭建了桥梁.
模式描述了要做什么, 价值观提供了动机, 原则把动机转化成实际行动.
程序的绝大多数开销是在他第一次部署之后才产生的.
应该选择那些提倡灵活并能带来及时收益的模式.对于立即增加成本却收效缓慢的模式, 最好多一点耐心, 先把他们放回口袋, 需要的时候再拿出来.
原则
局部化影响
组织代码结构时, 要保证变化只会产生局部化影响.
最小化重复
将逻辑和数据绑定
把逻辑与逻辑所处理的数据放在一起 , 如果有可能尽量放在一个方法中, 或者退一步, 放在一个对象里面, 最起码也要放到一个包下面. 发生变化时, 逻辑和数据很可能会被同时改动. 如果放在一起, 那么改动他们所造成的影响就会只停留在局部.
对称性
与其说是对称性, 还不如说是代码的一致性, 也就是方法的命名最好能做到一致, 符合人类的认知习惯, 比如有个add方法, 最好能提供个remove方法
不一致的代码:
void process(){ input(); count++; output(); }
勉强一致的代码:
void process(){ input(); incrementCount(); // 方法名没有体现意图而是在说实现细节 output(); }
最终一致的代码:
void process(){ input(); tally(); output(); }
声明式表达
尽可能用声明式来表达意图.
对那些只是陈述简单事实, 不需要一系列条件语句的程序片段, 如果用简单的声明方式写出来, 读者更容易.
作者举的例子是junit中通过注解来配置放在test suite中测试类.
变化率
把具有相同变化率的逻辑, 数据放在一起, 不同的进行分离
变化率也适应用于数据, 一个对象中所有成员变量的变化率应该差不多是相同的. 两个同时变化但是又和其他成员的变化步调不一致的 可能应该属于某个辅助对象, 比对金融票据中的数值和币种会同时变化.那么这两个字段最好放在辅助对象Money.
变化率原则也是对称性的一种, 只不过是时间上的对称.
类的模式
数据的变化比逻辑的变化要频繁的多, ----我不同意这个观点哈^_^
子类和超类之间的关系应该:我和超类很像, 只是有少许差异, 像那种对超类的某些方法进行覆盖并不是一种好的做法.
简单的超类名
重要的类, 尽量使用一个单数来为他命名
限定性的子类名
子类的名字:不仅要描述这些类像什么, 而且还要说明子类之间的区别是什么, 通常在超类的基础上扩展一两个词就可以得到子类名.
要从阅读者的角度来想想他们需要了解这个类的什么信息.
太长的类名读起来费劲儿, 太短又考验读者的记忆力.
抽象接口
为什么我们不能一口气理出系统中所有需要灵活性的地方呢, 因为需求和技术都在不可预测的变化
对灵活性的需要, 灵活性的成本, 何处需要灵活性的不可预测导致了只有当我们确信无疑需要灵活性时, 才能引入这种灵活性.
有版本的interface
一般情况下, 使用instanceof会降低灵活性, 因为这样会将代码与具体类绑定在一起. 这是一种丑陋的解决方案, 用来解决一类丑陋的问题.
值对象
这个十分巧妙. 至少我还没用过:( 只能看代码理解了, 在财务系统中, 把基本教义表现为不可变的数学值:
class Transaction{ int value; Transaction(int value, Account credit, Account debit){ this.value =value; credit.addCredit(this); debit.addDebit(this); } int getValue(){return value;} }
Transaction一旦创建, 它的值就无法改变.
值对象的所有状态都应该在构造时传入, 其他地方不再提供改变其内部状态的方式. 对值对象的操作总是返回新的对象, 操作的发起者要自己保存返回的对象.
对值对象, 最大的反对意见总是性能:创建那么多临时对象, 会让内存管理系统不堪重荷.
条件语句
条件语句if/else放在一个类中的好处:所有逻辑在一个类中, 阅读者不必四处寻找所有可能的计算路径. 缺点是:除了修改对象本身的代码之外, 没有其他办法修改它的逻辑.简而言之, 条件语句的好处在于简单和局部化, 如果用的太多, 这种好处就会变成弱点.
委派
解除条件语句的魔咒之一就是采用委派, 而委派的一个常用技巧:把发起委派的对象作为参数传递给接收委派的方法, 例子为证:
public class GraphicEditor { private RectangleTool tool; public void mouseDown() { tool.mouseDown(this); } public void add(RectangleFigure rectangleFigure) { } } public class RectangleTool { public void mouseDown(GraphicEditor editor) { editor.add(new RectangleFigure()); } }
匿名内部类
要用好匿名类内部类, API就必须极其简单, 或者有一个超类实现了绝大部分需要的方法, 总之匿名类应该尽量简单就对了. 这样也是为了避免扰乱阅读者的视线.
状态的模式
有效管理状态的关键在于:把相似的的状态放在一起, 确保不同的状态彼此分离.
变量
变量的类型由类型声明来表述就够了, 为此应该确保声明时的类型尽量清晰的描述变量的用途
如果作用域, 生命周期和类型都能用别的方式充分描述, 名称本身就可以只用于描述变量在计算逻辑中扮演的角色. 把需要承载的信息减少到最少.
常量
如果一个方法在调用时必须传入常量作为参数(比如setJustification(Justification.CENTERED)), 总可以针对每个常量值单独建立一个方法(比如justifyCentered()), 从而更好的表达你的意图.
按角色命名
一般而言, 名字被读到的次数比写出的次数要多的多, 所以在起命名时应该更重视可读性, 而不是输入的便利性.虽然使用缩写词的确可以让输入更快, 但是这个是以降低可读性为代价的.
在变量名中要表达的最主要的信息就是变量的角色, 这也让我们能够清晰简洁的命名, 如果命名遇到困难, 通常是因为我们还没有充分理解当前的计算逻辑
行为的模式
主体流
要清晰的表达程序的主体流, 用异常和防卫语句去表达不寻常的或者错误的情形.
消息
java中表达逻辑的主要手段是消息, 过程性语言使用过程调用来作为信息隐藏的机制.
对于
compute(){ input(); process(); output(); }
这样的过程性语言来说, 他的细节包含在步骤之中, 在我们理解compute()方法时不需要关心.而对于对象语言来说, 细节隐藏在作为消息的对象之中.理解了这一点, 就可以尽可能清晰和直接地表达逻辑, 而适当的推迟牵涉到的细节.
选择性消息
据个例子, 对于打算在若干个方法中显示一个图形, 可以发送一条多态的消息来传达出"选择将在运行时发生"的消息.
void display(Shape subject, Brush brush){ brush.display(subject); }
这里的brush和shape都是可以 进行选择的, 这样就可以进行自由的组合.
广泛的使用选择性消息可以使代码很少出现明确的条件语句, 每条选择性消息都是对未来扩展的一个邀请.
选择性消息的一个缺点就是阅读者可能要看好几个类才能理解一条特殊执行路径的细节.
反置性消息
本来是调用辅助类提供的方法来完成逻辑:
compute(){ input(); helper.process(); output(); }
这个写法的问题在于代码不够一致(对称性), 不美观. 反转一下, 并将input(), output()挪到helper中:
compute(){ new Helper(this).compute(); } Helper: compute(){ input(); process(); output(); }
解释性消息
主要说了两个, 一个是方法的命名要尽量说明意图, 而不是实现, 另外一个如果一行代码需要注释, 那么用方法封装之, 因为方法就是消息的载体.
异常流
应该尽可能清晰的表达主体流, 并在不模糊主体流的前提下尽可能清晰的表达这些异常路径.
顺序执行的程序是最容易阅读理解的.
卫述句
卫述句也就是短路检查语句.比如经过判断之后return, continue等
已检查异常
当抛出异常的程序和捕获异常的程序由不同的人编写实现, 抛出的异常未被捕获的风险更大. 因此java提供了已检查异常(非runtime exception)
方法的模式
方法的命名也是与阅读者沟通的机会.它可以告诉阅读者这段计算的目的何在, 让阅读者免受实现的影响.
揭示意图的名称
应该从潜在的调用者的想法出发, 根据调用者使用该方法的意图来给方法命名. 至于方法的实现策略可以通过另外的途径去传达.除非实现策略对用户有意义, 否则应该将其冲方法名种拿掉.
调用代码是在讲述一个故事, 好的方法名会让 讲述得更流畅.
重载方法
多个重载方法的目的应该一致, 不一致的地方应仅限于参数类型. 如果重载方法的返回类型不同, 会让代码难以理解, 最好为新的意图找一个新的名字, 不同的计算应该有不同的名称.
方法注释
对于沟通良好的代码来说, 很多注释完全是多余的. 编写这些注释, 以及维护这些注释与代码一致性的代价, 远高于他们带来的价值.
沟通仍然是所有实现模式的首要价值, 如果方法注释是最合适的沟通媒介, 那么写一个好注释吧.
转换方法
如果需要表达类型相近的对象之间的转换, 且转换的数量有限, 那么把转换表达成源对象的一个方法. 一般这样命名: asXxxx()
转换方法的缺点在于引入了源对象到目标对象之间的依赖关系, 如果原先不存在这样的依赖关系, 而仅仅为了转换方法而引入依赖是不值得的.另外提供过多的转换方法也是不合适,
转换构造器
他很适合用于将一个源对象转换成许多目标对象, 这样转换就分布在各个目标对象中.比如File(String), URL(String)等构造器是合适的, 如果提供String.asFile()就不合适了.
完整的构造器
构造器将客户绑定到一个具体类, 调用构造器意味着你愿意使用一个具体类, 如果你希望更抽象, 应该使用工厂方法.
工厂方法
如果要完成的工作比单纯的创建对象更复杂, 比如在缓存中记录对象, 那么工厂方法是合适的, 工厂方法一般都会引起阅读者的好奇, 想探究一下里面到底做了什么, 否则就不应该误导阅读者的这种好奇.
内部工厂
对于getX()方法来说, 如果x的计算很复杂, 那么需要将该过程封装到一个内部工厂方法中
getX(){ if(x == null){ x = computeX(); } return x; }
容器访问方法
如果容器不允许修改, 可以将容器的拷贝传递出去之外, 也可以将容器包装成一个不可修改的容器, 缺点之处在于修改的时候会引发不优化的隐藏.
另外一个是将容器方法返回一个将remove()方法throw UnsupportedOperationException()的一个Iterator
查询方法
如果一个对象有很多逻辑都依赖于另一个对象的状态, 可能意味着逻辑放错了地方, 比如:
if (x.isOK()){ x.invoke1(); }else x.invoke2();
这里可能x缺少了一个方法而导致对外暴露isOK(), invoke1(), invoke2()三个方法.
setter方法
setting方法是一个根据实现来命名的, 而不是意图. 如果用来给某个字段设置值比较合适, 但是如果是其他的目的则就应该另外考虑. 最好是能了解客户设置这个值是为了解决什么问题.
容器的实现模式
编程中最基本的变化种类之一就是数量的变化.
Set
Set有三种主要的实现:HashSet, LinkedHashSet和TreeSet(实现了SortedSet接口), HashSet速度最快, 但其中的元素是无序排列的. LinkedHashSet按照元素被加入容器的顺序来对元素排序, 但代价是添加删除元素要消耗30%的时间. TreeSet用Comparator来保护元素的顺序, 不过在添加删除元素或者检查元素是否存在时, 所花时间为logn, n为容器大小
查询
折半搜索只有对那些随机访问耗费时间为常数的列表才能起到提升性能的作用, 如ArrayList.
单元素容器
如果想把一个元素传到一个期望传入容器的借口中, 可以通过调用Collections.singleton()来进行转换, 这个方法会返回一个Set, 也有List, Map的版本, 只是这些容器都是不可修改的.
发表评论
-
<异类>读书笔记
2013-03-06 07:54 0成功者能够获得更多的机会,从而能变得更为成功。税收愈减免,富人 ... -
《python学习手册》学习笔记
2013-03-11 22:25 3469python格式化传参数非常赞,用数字标明位置,值得java学 ... -
<万历十五年>读书笔记
2013-03-11 22:27 1598在网上下了一个电子书, 但是貌似跟万历十五年没啥关系, 都是讨 ... -
《鸟哥的linux私房菜》读书笔记(部分)
2013-03-11 22:27 2066x86是一种微机系统硬件架构,另一种是苹果的mac的架构 l ... -
《你的灯亮了吗》读书笔记
2013-03-06 07:20 1509这是一本原本写给程序员的书 本书的四个问题: 搞清问题的来源 ... -
《小狗钱钱》读书笔记
2013-03-06 07:17 1479一本非常不错的理财学习入门书, 以童话的形式, 儿童的思维方式 ... -
《我的奋斗》读书笔记
2012-04-14 22:03 2064文字写的很幽默, 故事也基本都是一些平常人的故事,看到了一个特 ... -
《Java Performance》书评
2012-01-15 18:32 2965原文: http://java.dzone.com/rev ... -
《程序员应该知道的97件事》读书笔记
2012-01-15 18:36 2388一本关于写代码的文 ... -
《影响力》读书笔记
2011-11-05 14:47 1834从书名上很可能以为 ... -
《浪潮之巅》读书笔记
2011-11-05 14:44 1373作为一个中国人通过分析硅谷高科技公司的一系列传奇, 总结出这 ... -
《黑客与画家》读书笔记
2011-11-05 13:37 1820以前看过《rework》, 觉得是每一个小型创业公司的创业宝 ... -
《乔布斯传》读书笔记
2011-10-18 08:53 2848在ipad上看完了这本书, 写的还不错, 里面没有无聊的八 ... -
《细说Java》读书笔记
2011-10-05 15:01 1995国人写的, 感觉是一 ... -
《敏捷估计与规划》读书笔记
2011-10-05 12:08 3179这本书断断续续看了很长时间, 内容非常不错, 基本涵盖了sc ... -
《怪诞心理学》读书笔记
2011-10-05 09:44 1824既然是怪诞, 那么整本书涉及的内容并不是我们平常司空见怪的一 ... -
《番茄工作法图解》读书笔记
2011-09-28 09:02 2391番茄工作法是时间管 ... -
《Java开发超级工具集》读书笔记
2011-09-28 08:59 2101"工欲善其事必先利其器", 在平时的开发 ... -
《敏捷迭代开发管理者指南》读书笔记
2011-09-24 13:09 2217这是一本关于迭代开发 ... -
《解析极限编程》读书笔记
2011-09-24 13:03 1788不知道是kent beck的语 ...
相关推荐
状态机模式通过引入一个抽象状态类,例如TCPState,来定义各种状态的公共接口,然后由具体的子类(如TCPEstablished、TCPListening和TCPClosed)实现相应状态的行为。TCPConnection类持有一个代表当前状态的对象,并...
读书笔记:PHP设计模式讲解实现《大话设计模式》读书笔记和总结
读书笔记:Java实现的《大话设计模式》笔记
在实现这些模式时,需要考虑是否真正符合当前需求,避免滥用设计模式。理解模式的应用场景、优缺点以及如何将模式与具体需求相结合至关重要。例如,在选择工厂模式时,需要权衡简单工厂的便利性和工厂方法的可扩展性...
《设计模式学习笔记》主要探讨了GOF的23种设计模式以及类设计的基本原则,旨在帮助开发者理解和应用这些经过时间验证的成熟解决方案。...再次阅读设计模式的笔记,旨在深化理解,发掘设计模式在实际开发中的真正价值。
在《JAVA与模式读书笔记》中,我们探讨的是Java编程语言与设计模式的结合应用,这对于深入理解面向对象编程和提升软件开发能力至关重要。设计模式是软件工程中的最佳实践,它们是解决常见问题的模板,可以提高代码的...
开发者需要仔细阅读和理解RL78系列微控制器的技术手册,并根据手册指导来调整程序代码,以确保SNOOZE模式能够如预期那样降低功耗。 知识点五:老版本与新版本手册的对比 作者指出,老版本与新版本的数据手册在某些...
结构型模式:适配器模式(3种实现)、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式(3种实现)。行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、...
设计模式是软件工程中的一种通用解决方案,它是在特定上下文中解决常见问题的经验总结。这个“23种设计模式学习笔记”文档将引导...通过阅读“设计模式学习笔记.doc”,你可以逐一了解并掌握这些模式的原理和使用场景。
《HeadFirst设计模式学习笔记1--策略模式Demo》 在软件工程中,设计模式是一种解决常见问题的标准方案,它提供了一种在特定情况下组织代码的模板。策略模式是设计模式中的一种行为模式,它允许在运行时选择算法或...
读书笔记:图解设计模式spring实现
读书笔记:大话设计模式python实现
读书笔记:大话设计模式C++实现
读书笔记:图解设计模式python实现
读书笔记:图解设计模式 C# 实现。
抽象工厂模式则是创建一系列相关或相互依赖的对象,它提供一个接口来创建一组相关的产品,而无需指定具体的实现。比如爷爷带孙子去KFC,抽象工厂负责创建一系列相关的产品(如汉堡、薯条等)。抽象工厂模式同样遵循...
读书笔记:大话设计模式(C++实现)
读书笔记:《大话设计模式》C++实现
读书笔记:《大话设计模式》Python实现
读书笔记:《大话设计模式》Golang实现