`

《重构与模式》读书笔记

    博客分类:
  • Book
阅读更多

最近刚看完<重构与模式>这本书, 这本书很适合我的一直以来的观点, 大多数情况下, 模式的应用是一个渐进演变的过程, 坏味道也不是一开始就出现的, 而在一开始就想到用这个模式, 那个模式的, 很可能导致设计过度. 貌似重构与模式有一种天然的关系. 重构是手段, 模式是目的, 同时模式也为重构指明了方向和原则.书的原名<refactoring to parttens>很好的揭示了这本书的内容, 反而是中文名.....
<重构>林林总总的列出了我们会用到的各种重构手法, <设计模式>向我们描述了23种模式是个什么样子, 何种情况适用. 而这本书很好的将二者联系起来.
重构方法有很多, <重构与模式>中重点关注了几个重构手法和模式的关系, 而这几个重构手法相对来说不怎么好用, 或者很少人能用到, 可以归类为重构的高级用法. 我就是这样^_^, 大部分情况下重构的手法可能就是重命名, 抽取方法, 抽取类等等.
本书从创建, 简化, 泛化, 保护, 聚集操作几个方面来讲重构到模式, 对我个人而言, 简化和泛化应该是本书的精华所在. 每一个重构到模式的讲解按照<设计模式>的风格来安排(动机, 优缺点, 做法, 示例), 不过我觉得UML类图一目了然, 真正的是达到了一图胜千言的效果.

创建
Spring的流行, 导致创建, 实例化, 工厂对我们来说越来越陌生.
当代码中出现new 关键字的时候, 你头脑中那根敏感的神经是否已被刺痛?


Creation Method
场景:类中有多个构造函数, 因此很难决定在开发期间决定调用哪一个.
对策:用能够说明意图 返回对象实例的Creation Method替换构造函数.
比如原来是:
Xxx(x);
Xxx(x, y);
Xxx(x, y, z);
Xxx(x, y, z, m, n)....

可以改造成:
createOneXxx(x, y);
createTwoXxx(x, y, z);
createThreeXxx(x, y, z, m, n)...

向构造函数传入null值是一种不良的做法. 他会降低代码的可读性. 这往往出现在程序员找不到所需的准确构造函数, 转而创建了另一个更通用的构造函数.
如果你面对的类有Creation Method, 而且Creation Method分散了类的主要职责, 那么就应该相应的Creation Method重构成一个Factory.

将创建知识搬移到Factory
场景:用来实例化一个类的数据和代码在多个类中到处都是
对策:将有关创建的知识搬到一个Factory中.
当创建一个对象的知识散布在多个类中, 说明出现了创建蔓延场景: 将创建的职责放在了不应该承担对象创建任务的类中.

用Factory封装类
场景:直接实例化处在同一包结构, 实现同一接口的多个类
对策:把类的构造函数声明为非公有的, 并通过Factory来创建它们的实例.
通过一个Factory可以把处在同一包结构中的类与包结构之外的客户代码隔离起来.这样做的好处是可以保证客户代码通过通用接口与类交互, 很好的做到了面向接口编程这句老话.减少了具体实现的过多对外暴露, 另外Factory中的creation method更明确的表达了类的意图, 更容易理解.
对这个重构的很好的理解就是java.util中的Collections的synchronizedXxxx(), unmodifiedXxxx()方法的实现.

用Factory Method引入多态创建
场景:一个层次中的类都相似的实现了一个方法, 只是对象创建的步骤不同.
对策:创建调用Factory Method来处理实例化的方法的唯一超类版本.
在我看来, 这个重构实际上是披了件Template Method的外衣而已, 只是因为它跟创建过程沾了边, 所以要单独拿出来说.

用Builder封装Composite
场景:构造是复杂的, 重复的, 容易出错的工作.
对策:通过使用Builder处理构造细节来简化构造过程.
Builder的一个常见目的就是简化创建复杂对象的客户代码. 一旦Builder中实现了创建过程中的困难的或者冗长乏味的部分, 客户代码就可以指挥builder的创建过程, 而无需知道创建是如何完成的.Builder封装Composite的组装的另一个好处就是对客户代码和Composite代码的解耦. 因为Builder会封装Composite组件的创建过程, 而只向客户代码提供组合方法, 至于是如何Composite组件是什么样子, 如何组合客户代码不用关心.
这里有一点要求, builder的组装方法应该清晰的展现它的意图, 使得人们看到之后能明白他的功能.

简化
我们所编写的绝大部分代码不会从一开始就很简单, 为了使得代码简单, 必须要思考它复杂在什么地方.

组合方法
场景:你无法迅速的理解一个方法
对策:把方法的逻辑转换成几个同一细节层面上的, 能够说明意图的步骤
如果非要将Composed Method列为一种模式的话, 可能归为beck的实现模式的一种更恰当.
Composed Method的方法名描述了它实现了什么功能, 而他的方法体则描述了它如何实现这一功能.
如果说这种做法有什么缺点的话, 可能是会出现很多小方法.

用Strategy替换条件逻辑
场景:方法中条件逻辑控制着应该执行计算的哪个变体
对策:为每个变体创建一个strategy并使方法把计算委托到Strategy实例.
程序之中, 复杂的条件逻辑是最常导致复杂度上升的地点之一.
在实现基于Strategy的设计的时候, 需要考虑上下文类是如何包含它的Strategy的. 策略类所需要的数据有两种方式传入:把整个上下文类作为参数传入, 缺点是上下文类会暴露更多的方法出去, 另一个是把需要的数据都通过策略类的方法参数传入. 缺点是及时其他的策略类不需要这些参数也要传入.

将装饰功能搬移到Decorator中
场景:代码向类的核心职责提供装饰功能.
对策:将装饰代码搬移到Decorator.
如果要搬移装饰功能的类包含许多的公共方法, 那么Decorator模式不应该是重构的选择, 因为装饰类也需要实现要装饰类的所有公共方法, 则会导致很多无用的代码.
如果不熟悉使用对象组合"装饰"对象的方法, 那么就不适合使用这种模式.
包装类的选择也很重要, 好的包装类不会包含字段(比如状态), 因此与被包装类实现相同的接口是不错的做法.
包装类是采用组合的方式, 而采用继承可以将不同的功能放在具体的子类中实现, 但是却没法做到包装类的灵活组合, 实现复合功能.

用State替换状态改变条件
场景:控制一个对象状态转换的条件表达式过于复杂.
对策:用处理特殊状态和状态转换的State类替换条件语句.
把状态改变条件逻辑从类中除去, 并搬移到表示不同 的一系列类中, 可以产生更简单的设计. 如果类中的状态转移逻辑很容易理解, 就不需要重构到State模式(除非将来会添加更多的状态转换)
在重构到State模式之前, 考虑简单的重构(提炼方法)是否能够帮助我们整理状态转换的条件逻辑是很有好处的. 如果不能, 再考虑State模式, 从而得到更好理解, 更容易扩展的代码.
与策略重构一样, 也会产生一个委托过程, 将上下文类的方法委托到State类中来完成. 这样上下文就实现了状态无关.

用Composite替换隐含树
场景:用原生表示法(如String)隐含地形成了树结构
对策:用Composite替换原生表示法
觉得这个重构的使用场景非常有限.

用Command替换条件调度程序
场景:条件逻辑用来调度请求和执行操作.
对策:为每个动作创建一个Command, 把这些Command存储在一个集合中, 并用获取及执行Command的代码替换条件逻辑.
觉得采用Command模式里替换条件调度的适用性也有一定的限制, 就是条件判断逻辑要足够简单, 比如根据一个变量值来判断需要执行哪个操作, 另外, 条件逻辑有膨胀的趋势, 否则就是过度设计. 变简单为复杂.

泛化

形成Template Method
这个是我平时开发的最爱, 基本已经被我用烂了^_^, Spring里面的Template Method也是俯首皆是, 那些XxxxTemplate都是典型的模板方法模式.

提取Composite
这个用的也比较多, 简单的说就是在接口和实现之间, 再根据实现的内容, 再抽取一些公共的部分形成一个Composite, 不过我觉得用Abstract可能更合适一些.

其他的集中重构到模式很少用到

保护
用类替换类型代码
简单的说对简单类型(String, int)再包装一下, 以避免被赋非法值

其他的几种, 太简单, 可以无视了

聚集操作
聚集操作简单的说, 遍历集合对象, 并从每个对象中拿到需要的信息

将聚集操作搬移到Visitor
场景:一个方法从不同的类中聚集信息
对策:把聚集工作搬移到一个能够访问每个类以便聚集信息的Visitor中.
大多数时候你并不需要Visitor, 但是一旦你需要Visitor, 那就是真的需要Visitor了.
Visitor是在一个对象结构上执行某种操作的一个类, Visitor访问的类通常是互不相同的, 也就是说他们包含独特的信息, 并为这些信息提供独特的借口, 通过使用双分派, Visitor可以很容易的与不同的类进行交互. 这意味着每个类可以接受一个Visitor实例作为参数(accept方法).
真实世界中的许多Visitor的工作都是聚集信息.
分享到:
评论
2 楼 macrochen 2011-01-13  
java的
1 楼 AngelAndAngel 2011-01-13  
请问这本书里面的一些示例或者讲解都是以什么语言为基础的?

相关推荐

    重构与模式.pdf

    《重构与模式》开创性地深入揭示了重构与模式这两种软件开发关键技术之间的联系,说明了通过重构实现模式...《重构与模式》适于面向对象软件开发人员阅读,也可作为高等学校计算机专业、软件工程专业师生的参考读物。

    重构与模式 清晰.pdf

    本书开创性地深入揭示了重构与模式这两种软件开发关键技术之间的联系,说明了通过重构实现模式改善既有的设计,往往优于在新的设计早期使用模式。本书不仅展示了一种应用模式和重构的创新方法,而且有助于读者结合...

    重构与模式(中文版)

    重构与模式(中文版) 重构与模式(中文版) 重构与模式(中文版)

    重构与模式(Refactoring to patterns).part11.rar

    一共12个包,全下载解压 本书开创性地深入揭示了重构与模式这两种软件开发关键技术之间的联系,说明了通过重构实现模式改善既有的设计,往往优于在新的设计早期使用模式。本书不仅展示了一种应用模式和重构的创新...

    重构与模式(Refactoring to patterns).part05.rar

    一共12个包,全下载解压 本书开创性地深入揭示了重构与模式这两种软件开发关键技术之间的联系,说明了通过重构实现模式改善既有的设计,往往优于在新的设计早期使用模式。本书不仅展示了一种应用模式和重构的创新...

    重构与模式pdf高清发版

    经典书籍 只要1分 《重构与模式》 作者: [美]Joshua Kerievsky 出版社: 人民邮电出版社 译者: 杨光 / 刘基诚 出版年: 2006年10月 页数: 312

    重构与模式.[美]Joshua Kerievsky(带详细书签).pdf

    本书开创性地深入揭示了重构与模式这两种软件开发关键技术之间的联系,说明了通过重构实现模式改善既有的设计,往往优于在新的设计早期使用模式。本书不仅展示了一种应用模式和重构的创新方法,而且有助于读者结合...

    [电子书] 重构与模式

    ☆ 资源说明:☆ [Addison-Wesley Professional] 重构与模式 [Addison-Wesley Professional] Refactoring to Patterns

    重构与模式(Refactoring to patterns).part01.rar

    一共12个压缩包,全下载解压 本书开创性地深入揭示了重构与模式这两种软件开发关键技术之间的联系,说明了通过重构实现模式改善既有的设计,往往优于在新的设计早期使用模式。本书不仅展示了一种应用模式和重构的...

    重构与模式(1-4)

    重构与模式(1-4)

    重构与模式

    重构与模式

    重构与模式 Addison Wesley Refactoring To Patterns

    重构与模式 Refactoring To Patterns 如何让代码优美,更具可维护性

    重构与模式 (高清 中文 带书签)

    经典不解释 高清 中文 带书签 看了《重构-改善既有代码的设计》,再看《重构与模式》

    [重构与模式].(美国)Joshua.Kerievsky.清晰版(PDF和DJVU两个版本)

    该压缩包中包含两个清晰版本: [重构与模式].(美国)Joshua.Kerievsky.清晰版.PDF [重构与模式].(美国)Joshua.Kerievsky.清晰版.djvu PDF版本是DJVU转换而来的,所以清晰度稍差!

    面向对象重构与模式设计

    面向对象重构与模式设计 软件模式的伟大之处,就在于它们传达了许多有用的设计思想。所以,在学习了大量模式之后,就理应成为非常优秀的软件设计人员,不是吗?当学习、使用了几十个模式后,我也曾这样认为。模式...

    重构与模式_Joshua Kerievsky

    本书开创性地深入揭示了重构与模式这两种软件开发关键技术之间的联系,说明了通过重构实现模式改善既有的设计,往往优于在新的设计早期使用模式。本书不仅展示了一种应用模式和重构的创新方法,而且有助于读者结合...

    重构与模式(Refactoring.to.Patterns)(中英版)

    重构与模式(Refactoring.to.Patterns)(中英版)

    Refactoring To Patterns《重构与模式》英文版

    Refactoring To Patterns 重构与模式 英文版

Global site tag (gtag.js) - Google Analytics