自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(66)
  • 收藏
  • 关注

原创 第一章 设计之命题

将对一门艺术的领悟联系并应用到另一门艺术中,经历若干次这样的经历而有所悟,脑海里自然就孕育出了新思想。———培根1.培根所言是否正确设计过程本身是否存在那些适用于广泛设计载体的不便的属性?2.什么是设计计划,思维,后续执行。三步:概念性构想的形成,在真实的媒体中实现,在真实的体验中与用户交互。根本的软件构造部分是形成其概念性结构的心智过程,称之为次要的部分是其实现过程。交互

2011-10-31 11:28:27 388

原创 9.8 introduce assertion

某一段代码需要对程序状态做出某种假设。动机:使用断言明确标记假设。断言是一个条件表达式,应该总是真,如果失败,表示程序员犯了错误。做法:如果发现代码假设某个条件始终为真,就加入一个断言明确说明这种情况。断言用来检查“一定必须为真”的条件。

2011-10-20 22:22:12 505

原创 3.22 comments (过多的注释)

如果需要注释来解释一块代码,试试extract method如果函数已经提炼出来,还需要注释,试试rename method。如果还需要注释说明某些系统规格,试试introduce assertion

2011-10-20 22:15:51 417

原创 3.21 refused bequest

如果子类复用类超的行为,却又不愿意支持超类的接口。应该运用replace inheritance with delegation达到目的。

2011-10-20 22:13:47 468

原创 3.20 Data class(纯稚的数据类)

拥有一些字段,以及用于访问这些字段的函数,除此之外一无长物。这样的类只是一种不会说话的数据容器,它们几乎一定被其他类过份细琐的操控着。使用encapsulate field封装起来。使用encapsulate collection把它们封装起来。对于那些不该被其他类修改的字段,请运用remove setting method。搬移相关函数后,运用hide method。

2011-10-20 22:07:56 676

原创 7.8 Introduce local extension (引入本地扩展)

需要为服务类提供一些额外函数,但你无法修改这个类。建立一个新类,使它包含这些额外函数。让这个扩展品成文源类的子类或包装类。动机:所谓本地扩展是一个独立的类,但也是被扩展类的子类型:它提供源类的一切特性,同时额外添加新特性。在任何使用源类的地方,都可以使用本地扩展取而代之。如果有其他对象引用了就对象,就同时有两个对象保存了原数据。做法:建立一个扩展类,将它作为原始类的子类或包

2011-10-20 21:47:22 620

原创 7.7 introduce foreign method(引入外加函数)

需要为提供服务的类增加一个函数,但你无法修改这个类。动机:添加外加函数实现无法修改服务类的新功能。做法:在客户类中建立一个函数,用来提供你需要的功能。=》这个函数不应该调用客户类的任何特性。如果它需要一个值,把该值当作参数传给它。以服务类实例作为该函数的第一个参数。旧代码Date newStart = new Date(previousend.getYear(),

2011-10-20 21:35:17 643

原创 3.19 Incomplete library class(不完美的库类)

如果你只想修改库类的一两个函数,可以运用introduce foreign method;如果想要添加一大堆额外行为,就得运用introduce local extension。

2011-10-20 21:25:04 1405

原创 11.7 extract superclass (提炼超类)

两个类有相似特性为这两个类新建一个超类,将相同特性移至超类。动机:两个类以相同的方式做类似的事情,或者以不同的方式做类似的事情。做法:为原本得类新建一个空白的抽象超类。运用pull up field,pull up method和pull up constructor body逐一将子类的共同元素上移到超类。检查留在子类中的函数,看它们是否还有共通成分。如果有,可以使用

2011-10-20 21:10:34 702

原创 3.18 alternative classes with different interfaces(异曲同工的类)

如果两个函数做同一件事,却有着不同的签名,请运用rename method根据他们的用途重新命名。或许可以使用extract superclass。

2011-10-20 20:51:29 449

原创 11.11 replace inheritance with delegation(以委托取代继承)

某个子类只使用超类接口中的一部分,或是根本不需要继承而来的数据。在子类中新建一个字段用以保存超类;调整子类函数,令它改而委托超类;然后去掉两者之间的继承体系。动机:一开始继承了一个类,随后发现超类中的许多操作并不真正适用于子类。这种情况下,你所拥有的接口并未真正反映出

2011-10-19 11:29:09 1063 1

原创 8.8 change bidirectional association to unidirectional (将双向关联改为单向关联)

两个类之间有双向关联,但其中一个类如今不再需要另一个类的特性。动机:双向关联很有用,但你必须为它付出代价,那就是维护双向连接。大量的双向连接也很容易造成“僵尸对象”。双向关联也迫使两个类之间有了依赖:对其中一个类的任何修改,都可能引发另一个类的变化。做法:

2011-10-19 10:59:00 1371

原创 3.17 inappropriateintimacy (狎昵关系)

有时会看到两个类过于亲密,花费太多时间去探究彼此的private成分。可以采用move method和move field划清界限。可以运用change bidrectional association to unidirectional让其中一个类对另一个类斩断情丝。如果情

2011-10-19 10:39:19 946

原创 6.2 inline method (内联函数)

一个函数的本体与名称同样清楚易懂。在函数调用点插入函数本体,然后移除该函数。动机:某些函数,其内部代码和函数名称同样清晰易懂。可以去掉该函数。手上有一群组织不合理的函数,将它们都内联到一个大型函数中,再从中提炼出组织合理的小型函数。如果别人使用了太多间接层,使

2011-10-19 10:28:45 991

原创 7.6 remove middle man(移除中间人)

某个类做了过多的简单委托动作。让客户直接调用受委托类。动机:随着受托类的特性越来越多,这一过程让你痛苦不已,服务类完全变成一个中间人,此时应该让客户直接调用受托类。做法:建立一个函数,用以获得受托对象。对于每个委托函数,在服务类中删除该函数,并让需要调用该

2011-10-19 10:20:04 457

原创 3.16 Middle Man(中间人)

过度使用委托,某个类的接口有一半的函数都委托给其他类,这样就是过度运用。应该使用remove middle man,直接和真正负责的对象打交道。如果这样的函数只有少数几个,可以运用inline method把它们放进调用端。如果这些middle man还有其他行为,可以运用rep

2011-10-19 10:06:55 432 1

原创 7.5 hide delegate (隐藏委托关系)

客户通过一个委托类来调用另一个对象。在服务类上建立客户所需的所有函数,用以隐藏委托关系。动机:封装意味每个对象都应该尽可能少了解系统的其他部分。如此一来,一旦发生变化,需要了解这一变化的对象就会比较少。如果某个客户先通过服务对象的字段得到另一个对象,然后调用后者的

2011-10-19 10:02:41 1011

原创 3.15 message chains (过度耦合的消息链)

一个对象请求另一个,后者在请求下一个对象,....这就是消息链。采取这种方式,意味客户代码将与查找过程中的导航结构紧密耦合,一旦对象间的关系发生任何变化,客户端就不得不做出相应修改。这时候应该使用hide delegate。通常更好的手法:先观察消息链最终得到的对象是用来

2011-10-19 09:50:05 1432

原创 3.14 temporary field (令人迷惑的暂时字段)

某个对象的实例变量仅为某种特定情况而设。在变量未被使用的情况下猜测当初其设置目的,会让你发疯。请使用extract class给这些变量创造一个家。如果类中有一个复杂算法,需要好几个变量,往往就可能导致temporary field,由于实现者不希望传递一长串参数,所以他

2011-10-19 09:43:33 1142

原创 3.13 speculative generality (夸夸其谈未来性)

如果所有装置都会被用到,那就值得那么做,如果用不到,就不值得。用不上的装置只会挡你的路,所以,把它搬开。如果某个抽象类其实没有太大作用,请运用collapse hierarchy,不必要的委托可运用inline class除掉。如果函数的某些参数未被用上,实施remove p

2011-10-19 09:35:56 691

原创 11.9 collapse hierarchy (折叠继承体系)

超类和子类之间无太大区别。将它们合为一体。动机:继承体系很容易变的过分复杂。所谓重构继承体系,往往是将函数和字段在体系中上下移动。完成这些动作后,很可能发现某个子类并未带来该有的价值,因此需要把超类与子类合并起来。做法:选择想移除的类,是超类还是子类。使用

2011-10-19 09:30:52 1066

原创 3.12 lazy class(冗赘类)

你所创建的每一个类,都得有人去理解它,维护它,这些工作都是要花钱的。如果一个类的所得不值其身价。它就应该消失。某个类原本对得起自己的身价,但重构使它身形缩水,不再做那么多工作;或开发者事前规划了某些变化,并添加一个类来应付这些变化,但变化实际上没有发生。如果某些子类没有工

2011-10-19 09:26:06 679

原创 3.11 parallel inheritance hierarchies (平行继承体系)

如果为某个类增加一个子类,必须也为另一个类相应增加一个子类。如果发现某个继承体系的类名称前缀和另一个继承体系的类名称前缀完全相同,便是这种坏味道。策略:让一个继承体系的实例引用另一个继承体系的实例。如果再接再励使用move method和move field,就可以将引用端的

2011-10-19 09:20:49 1412

原创 9.7 introduce Null object (引入null对象)

需要再三检查对象是否为null。将null值替换为null对象。动机:当某个字段是null时,多态可以扮演另一个较不直观的用途。控对象一定是常量,它们的任何成分都不会发生变化。做法:为源类建立一个子类,使其行为就像是源类的null版本。在源类和null子类

2011-10-18 15:16:56 877

原创 10.6 replace parameter with explicit methods(以明确函数取代参数)

有一个函数,完全取决于参数值而采取不同行为。针对该参数的每一个可能值,建立一个独立函数。动机:如果某个参数有多种可能的值,而函数内又以条件表达式检查这些参数值,并根据不同参数值做出不同的行为,那么就应该使用本项重构。如果以参数决定函数行为,那么函数用户不但需要观察该函

2011-10-18 14:42:05 621

原创 9.6 replace conditional with polymorphism (以多态取代条件表达式)

条件表达式,根据对象类型的不同而选择不同的行为。将这个条件表达式的每一个分支放进一个子类内的覆写函数中,然后将原始函数声明为抽象函数。动机:多态使你不必编写明显的条件表达式。如果同一组条件表达式在程序许多地方出现,那么使用多态的收益是最大的。做法:使用re

2011-10-18 11:14:23 1792

原创 3.10 witch statements(switch 惊悚现身)

面向对象程序的一个最明显特征是:少用switch语句。switch语句常常根据类型码进行选择,所以应该使用extract method将switch语句提炼到一个独立函数中,再以move method将它搬移到需要多态性的那个类里。此时决定是否使用replace type c

2011-10-18 10:46:30 765

原创 8.5 replace array with object (以对象取代数组)

有一个数组,其中的元素各自代表不同的东西。以对象替换数组,对于数组中每个元素,以一个字段来表示。动机:一个数组容纳了多种不同对象。可以运用字段名称和函数名称来传达这样的信息。做法:新建一个类表示数组所拥有的信息,并以其中一个public字段保存原先的数组。

2011-10-17 11:21:49 629

原创 8.15 replace type code with state/strategy (以state/strategy取代类型码)

有一个类型码,会影响类的行为,但你无法通过继承手法消除它。以状态对象取代类型码。动机:如果类型码的值在对象生命期中发生变化或其他原因使得宿主类不能被继承。如果打算在本次重构后以replace conditional with polymorphism简化一个算法,

2011-10-17 11:05:59 594

原创 8.14 replace type code with subclasses (以子类取代类型码)

有一个不可变的类型码,会影响类的行为。以子类取代这个类型码。动机:如果类型码会影响宿主类的行为,那么最好的办法就是借助多态来处理变化行为。以类型码的宿主类为基类,针对每种类型码建立相应的子类。一下情况不能那么做:类型码值在对象创建之后发生了变化;由于某些原因,

2011-10-17 10:38:23 659

原创 8.13 replace type code with class(以类取代类型码)

类之中有一个数值类型码,但它并不影响类的行为。以一个新的类替换该数值类型码。动机:如果带着一个有意义的符号名,类型码的可读性还是不错的。问题在于,符号名终究只是个别名,编译器看见的,进行类型检验的,还是背后那个数值。任何接受类型码作为参数的函数,所期望的实际上是一个数

2011-10-17 10:04:50 634

原创 8.2 replace data value with object(以对象取代数据值)

你有一个数据项,需要与其他数据和行为一起使用才有意义。将数据项变为对象。动机:开发初期,往往决定以简单的数据项表示简单的情况。但是,随着开发的进行,可能会发现,这些简单数据项不再那么简单了。做法:为待替换数值新建一个类,在其中声明一个final字段,其类型和源

2011-10-17 09:27:26 520

原创 3.9 primitive obsession(基本类型偏执)

对象的一个极大价值在于:它们模糊了横旦于基本数据和体积较大的类之间的界限。可以运用replace data value with object将原本单独存在的数据值替换为对象,从而走出传统的洞窟。如果想要替换的数据值是类型码,而它并不影响行为,则可以运用replace type

2011-10-17 09:08:36 1536

原创 3.8 data clumps(数据泥团)

常常可以在很多地方看到相同的三四项数据:两个类中相同的字段,许多函数签名中相同的参数。这些总是绑在一起出现的数据真应该拥有属于他们自己的 对象。首先请找出这些数据以字段形式出现的地方,运用extract class将它们提炼到一个独立对象中。然后将注意力转移到签名函数上,运用in

2011-10-17 09:00:31 3130

原创 3.7 Feature envy(依恋情结)

函数对某个类的兴趣高过对自己所处类的兴趣。一个函数往往会用到几个类的功能,那么它究竟该被置于何处呢?判断哪个类拥有最多被此函数使用的数据,然后就把这个函数和那些数据摆在一起。将总是一起变化的东西放在一起。数据和引用这些数据的行为总是一起变化,但也有例外。如果例外出现,我们

2011-10-17 08:55:00 1329

原创 7.4 inline class (将类内联化)

某个类没有做太多事情。将这个类的所有特性搬移到另一个类中,然后移除原类。动机:如果一个类不再承担足够责任,不再有单独存在的理由,将此萎缩类塞进另一个类中。做法:在目标类上声明源类的public协议,并将其中所有函数委托至源类。=》如果“以一个独立接口表示源

2011-10-16 15:47:31 802

原创 7.2 move field (搬移字段)

程序中,某个字段被其所驻类之外的另一个类更多地用到。动机:随着系统的发展,会发现自己需要新的类,并需要将现有的工作责任拖到新的类中。做法:如果字段的访问级是public,使用encapsulate field将它封装起来。=》如果你有可能移动那些频繁访问该字段

2011-10-16 15:33:34 606

原创 7.1 move method (搬移函数)

程序中,有个函数与其所驻类之外的另一个类进行更多交流:调用后者,或被后者调用。在该函数最常引用的类中建立一个有着类似行为的新函数。将旧函数变成一个单纯的委托函数,或是将旧函数完全移除。动机:如果一个类有太多行为,或如果一个类与另一个类有太多合作而形成高度耦合,我就会搬

2011-10-16 15:15:48 792

原创 3.6 shotgun surgery(散弹式修改)

如果没遇到某种变化,都必须在许多不同的类内做出许多小修改,你所面临的坏味道就是shotgun surgery。应该使用move method和move field把所有需要修改的代码放进同一个类。如果眼下没有合适的类可以安置这些代码,就创造一个。通常可以运用inline cl

2011-10-16 14:42:32 1370 1

原创 3.5 divergent change(发散式变化)

如果某个类经常因为不同的原因在不同的方向上发生变化,divergent change就出现了。针对某一外界变化的所有相应修改,都只应该发生在单一类中,而这个新类内的所有内容都应该反映此变化。为此,应该找出某特定原因而造成的所有变化,然后运用extract class将它们提炼到另

2011-10-16 14:36:56 1020

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除