OOD启思录
【书名 】:OOD启思录
【出版社 】:人民邮电出版社
【作者 】:Arthur J.Riel
【评价 】:★★★★★★★☆☆☆
【正文 】:
----------------------------------------------------------------------------------------------------0001: 确立指导性原则。----------------------------------------------------------------------------------------------------0002: 经验原则的重要程度取决于违反这条原则造成的后果有多严重。不过,不同的应用领域,所造成的后果的严重程度不同。因此,经验原则的优先级随着应用领域的不同而不同。----------------------------------------------------------------------------------------------------0003: 经常需要在复杂性和灵活性之间进行取舍。----------------------------------------------------------------------------------------------------0004: 软件变得越来越复杂,所以我们必须达到离机器更远的一个新的抽象层次。面向对象技术比结构化方法提高了一个抽象层次。这并不意味着自底向上的结构化编程范型是错误的,面向对象的范型就一定正确。如果能用的内存只有4K,无疑,结构化编程是非常适合的。----------------------------------------------------------------------------------------------------0005: 结构化编程是中央集权式的,而面向对象是分布式的。这一范型的迁移,意味着思考方式的转变。面向对象的学习曲线就是面向结构的遗忘曲线。----------------------------------------------------------------------------------------------------0006: 如果系统中有一个位居中央的全能类,那么这样的系统依然是面向结构的。----------------------------------------------------------------------------------------------------0007: 模式:已知问题的独立于领域的解决方案,或面向对象架构中的有趣结构。----------------------------------------------------------------------------------------------------0008: 思维是独立于知识的。----------------------------------------------------------------------------------------------------0009: 宗教般的热情。----------------------------------------------------------------------------------------------------0010: 革命家与改革家。----------------------------------------------------------------------------------------------------0011: 软件危机的真正原因是根本复杂性。根本复杂性来自于这一事实:软件本质上就是复杂的,没有哪种方法学或工具可以消除这种复杂性。----------------------------------------------------------------------------------------------------0012: 瀑布模型不适合于不熟悉的领域。----------------------------------------------------------------------------------------------------0013: 对于面向对象的开发者来说,软件开发的迭代模型是理所当然的选择。----------------------------------------------------------------------------------------------------0014: 现实世界中的复杂实体是逐渐生长而成的,而不是创建而得的。----------------------------------------------------------------------------------------------------0015: C++是多范型语言。----------------------------------------------------------------------------------------------------0016: 不要把面向对象和好等同起来。使用纯粹面向对象语言的开发者也可能是糟糕的开发者。没有哪种技术能完全防止开发者的愚蠢行为。----------------------------------------------------------------------------------------------------0017: 代码尺度和灵活性成反比。----------------------------------------------------------------------------------------------------0018: 在粒度和灵活性之间取得平衡。----------------------------------------------------------------------------------------------------0019: 面向对象范型还有未解决的问题。----------------------------------------------------------------------------------------------------0020: 现实世界中,有很多东西是我们会使用但不会制造的。----------------------------------------------------------------------------------------------------0021: 一个对象具有的四个方面: ●身份标识:可能只是内存中地址 ●类的属性(静态的)和对象的属性(动态的) ●行为:从实现者的角度看 ●公开接口:从用户的角度看----------------------------------------------------------------------------------------------------0022: 对象应当被看作机器,机器只为提出恰当请求的人执行公开接口所定义的操作。----------------------------------------------------------------------------------------------------0023: 对象行为,公开接口,消息是一个事物的不同视角。----------------------------------------------------------------------------------------------------0024: 消息分为同步和异步。----------------------------------------------------------------------------------------------------0025: 对象所能响应的消息列表称为协议。----------------------------------------------------------------------------------------------------0026: 类不能依赖它的使用者。----------------------------------------------------------------------------------------------------0027: 尽量减少类的协议中的消息。----------------------------------------------------------------------------------------------------0028: 不要把实现细节放到类的公开接口中。----------------------------------------------------------------------------------------------------0029: 不要以用户无法使用或不感兴趣的东西扰乱类的公开接口。----------------------------------------------------------------------------------------------------0030: 类之间有5种形式的耦合关系: ●零耦合:最佳形式 ●导出耦合:一个类依赖于另一个类的公开接口。也就是说,这个类用到另一个类的一个或多个操作 ●授权耦合:C++中的友元类 ●自行耦合:与授权耦合差不多 ●暗中耦合:耦合最危险的形式----------------------------------------------------------------------------------------------------0031: 类之间应该零耦合或只有导出耦合关系。----------------------------------------------------------------------------------------------------0032: 类应当表示一个关键抽象:关键抽象经常以名词形式出现,并伴随着需求约定。每个关键抽象都应当只映射到一个类。如果它被映射到多个类,那么设计者可能是把每个功能都表示为一个类了。如果多个关键抽象被映射到同一个类,那么设计者可能在创建一个集中化系统。----------------------------------------------------------------------------------------------------0033: ADT:抽象数据类型,有的时候是“类”的同义词。----------------------------------------------------------------------------------------------------0034: 确保建模的抽象概念是类,而不只是对象扮演的不同角色。----------------------------------------------------------------------------------------------------0035: 面向对象范型始终把数据放在开发者脑海中的优先位置,同时把功能放在次要的位置上。----------------------------------------------------------------------------------------------------0036: 面向对象的前景并不是一片光明的。----------------------------------------------------------------------------------------------------0037: 原则首先需要开发者理解它,其次,开发者必须坚持遵循它。然而,理解总是简单,坚持太难。----------------------------------------------------------------------------------------------------0038: 对含有大量接口的类要小心,可能是将几个类合并到了一起。----------------------------------------------------------------------------------------------------0039: 功能冗余。----------------------------------------------------------------------------------------------------0040: 属性冗余。----------------------------------------------------------------------------------------------------0041: 模型不应依赖于界面,界面应该依赖于模型。----------------------------------------------------------------------------------------------------0042: 尽可能按照现实世界建模。----------------------------------------------------------------------------------------------------0043: 软件开发者3个月后很可能根本不记得他们曾经做过什么,或者为什么这么做。----------------------------------------------------------------------------------------------------0044: 做软件和写文章一样。----------------------------------------------------------------------------------------------------0045: 对于只有一个有意义行为的类要特别小心,很可能这个类是多余的。----------------------------------------------------------------------------------------------------0046: 如果类的名字很难避免使用动词,那么这个类可能只是操作。----------------------------------------------------------------------------------------------------0047: 代理类。----------------------------------------------------------------------------------------------------0048: 人们希望最好每盘录像带都自带一个播放器,这样就把控制器和实体信息封装到了同一个包装中。----------------------------------------------------------------------------------------------------0049: 对象或类之间的关系: ●使用关系(基于对象) ●包含关系(基于对象) ●继承关系(基于类) ●关联关系(基于对象)----------------------------------------------------------------------------------------------------0050: 尽量减少类和协作者之间传递的消息的数量。----------------------------------------------------------------------------------------------------0051: 如果类包含另一个类的对象,那么包含类应当给被包含的对象发送消息。也即:包含关系总意味着使用关系。----------------------------------------------------------------------------------------------------0052: 典型的面向结构的设计者在进行高层次设计时常常忍不住要知道实现的细节。----------------------------------------------------------------------------------------------------0053: 类中定义的大多数方法都应当在大多数时间里使用大多数数据成员。----------------------------------------------------------------------------------------------------0054: 类包含的对象数目不应当超过开发者短期记忆的容量。这个数字常常是6。----------------------------------------------------------------------------------------------------0055: 大多数人在短期记忆中能保留的事务的数目是5~7之间,这在心理学的世界中是广泛接受的标准数字。----------------------------------------------------------------------------------------------------0056: 当类包含多于6个数据成员时,可以把逻辑相关的数据成员划分为一组,然后用一个新的包含类去包含这一组成员。----------------------------------------------------------------------------------------------------0057: 让系统功能在窄而深的继承体系中垂直分布,不过,窄而深的层次结构的一个已知问题是效率。----------------------------------------------------------------------------------------------------0058: 被同一个类包含的对象之间不应该有使用关系。----------------------------------------------------------------------------------------------------0059: 值包含和引用包含:值包含意味着一个对象包含另一个对象,而引用包含意味着一个对象包含另一个对象的指针。值包含要求两个对象同生共死,而引用包含则允许对象包含可选组件,还允许在一组对象之间共享一个对象。----------------------------------------------------------------------------------------------------0060: 同一阶级之间的互斗,产生了分裂。----------------------------------------------------------------------------------------------------0061: 类的保护区域介于公有和私有之间。对派生类的实现者来说是公有的,对使用者来说是私有的。----------------------------------------------------------------------------------------------------0062: 派生类不能去除基类的任何功能。否则,任何东西都可以成为其他东西的特殊类型了,只要去除基类的所有行为,并且把所有新行为增加到派生类中就可以了。如:狗去掉所有狗的行为,实现猫的行为,那么狗就成了猫的派生类。----------------------------------------------------------------------------------------------------0063: 基类不应当知道关于它们的派生类的任何信息。如果基类知道它们的派生类,那么就意味着,如果基类有了一个新的派生类,基类中的代码就必须修改。这不是基类和派生类所表示的抽象之间应有的依赖关系。----------------------------------------------------------------------------------------------------0064: 基类中的所有数据成员都应当是私有的,不应当使用保护数据。----------------------------------------------------------------------------------------------------0065: 理论上,继承层次体系应当深一点,越深越好。在实践中,继承层次体系的深度不应当超出一个普通人的短期记忆能力,一个广为接受的数字是6。----------------------------------------------------------------------------------------------------0066: 寻求设计复杂性和灵活性之间的平衡。----------------------------------------------------------------------------------------------------0067: 所有的抽象类都应当是基类。----------------------------------------------------------------------------------------------------0068: 经验原则往往是矛盾的,这个时候应该根据具体情况,具体分析。----------------------------------------------------------------------------------------------------0069: 把数据,行为或接口的共性尽可能放到继承层次体系的高端。违反这条原则意味着某个特定抽象需要被重新设计并且在每个派生类中重新实现,而不是只在基类中修改就好了。----------------------------------------------------------------------------------------------------0070: 多态防止了case和if的使用。----------------------------------------------------------------------------------------------------0071: 如果两个或多个类共享数据部分,而没有公共的行为,那么应当把公共数据放在一个类中,每个共享这些数据的类都包含这个类。----------------------------------------------------------------------------------------------------0072: 如果两个或多个类共享数据部分和行为部分,那么这些类的每一个都应当从一个表示了这些数据和行为的公共基类继承。----------------------------------------------------------------------------------------------------0073: 大部分类库是以源代码的形式销售的。----------------------------------------------------------------------------------------------------0074: 类会成长,也会成熟和老去。----------------------------------------------------------------------------------------------------0075: 任何事物都是一个轮询系统,轮询和中断的区别在于你的视点。当我们在硬件中轮询时,我们习惯称之为中断。----------------------------------------------------------------------------------------------------0076: 名词是类和对象的良好的候选者,动词是这些类和对象的操作的良好候选者,形容词则可能意味着继承。----------------------------------------------------------------------------------------------------0077: 在苹果中有一个“种类”属性,而水果中确没有,为什么对于水果来说建模成一个继承层次结果,而苹果建模成一个属性:决定性的问题是,这个属性的值是否会影响类的行为,如果不会就应当建模成一个属性。----------------------------------------------------------------------------------------------------0078: 在运行时改变对象的类型都是一个很昂贵的错误。----------------------------------------------------------------------------------------------------0079: 人们在评审的时候经常花数小时在争论他们认为很重要的命名问题。----------------------------------------------------------------------------------------------------0080: 讨论的成本。----------------------------------------------------------------------------------------------------0081: 不要把类的对象变成派生类。对任何只有一个实例的派生类都要多加小心。----------------------------------------------------------------------------------------------------0082: 在创建继承层次结构时会遇到的一个有趣的问题是,设计者可能会试图在派生类中屏蔽基类的方法。这样的想法是错误的。----------------------------------------------------------------------------------------------------0083: 生物学家的分类依据是什么?----------------------------------------------------------------------------------------------------0084: 不要相信一家之言,实践是检验真理的唯一标准。----------------------------------------------------------------------------------------------------0085: 很多问题常常仅仅是命名的问题。如:苹果去皮,桃去核可以同一命名为初始化,那么就可以在基类中提供这个行为。----------------------------------------------------------------------------------------------------0086: 食言。----------------------------------------------------------------------------------------------------0087: 没有最好的解决方案,所有的方案都有需要解决的问题。----------------------------------------------------------------------------------------------------0088: 在创建类的时候,试着创建可复用的框架,而不是可复用的组件。----------------------------------------------------------------------------------------------------0089: 可复用的设计比可复用的代码更有价值。----------------------------------------------------------------------------------------------------0090: 开发可复用的设计,预示着开发成本的增加,很少有公司愿意为了明天可以省下更多的时间和金钱而在今天支付额外的时间和金钱。----------------------------------------------------------------------------------------------------0091: 继承本质上是一种白盒设计过程,而包含本质上是一种黑盒设计过程。每当可以在白盒和黑盒之间选择时,请选择黑盒。----------------------------------------------------------------------------------------------------0092: 有两种实现关联关系的主要方法,一种是使用引用属性,另一种是使用一个第三方类。第一种方式在一对一和一对多时很常用。第二种在多对多时很常用。----------------------------------------------------------------------------------------------------0093: 对于需要很复杂的操作才能获得属性,可以采取惰性填充。数据库的程序中的一些情况就可以这样设计。----------------------------------------------------------------------------------------------------0094: 功能应该分布在所有的类中,并且是均匀的。如果出现聚集,那么很可能是糟糕的设计。----------------------------------------------------------------------------------------------------0095: 类的数据和行为与对象的数据和行为的区别是关键字:static----------------------------------------------------------------------------------------------------0096: 模板是一种语言级的机制,使用一种描述来表达一组类。----------------------------------------------------------------------------------------------------0097: 面向对象设计实际上有两个方面:逻辑设计和物理设计。----------------------------------------------------------------------------------------------------0098: 物理设计不能破坏逻辑设计,但是逻辑设计应该在物理设计的限制下进行。----------------------------------------------------------------------------------------------------0099: 包装器可以封装非面向对象的子系统,例如关系数据库。----------------------------------------------------------------------------------------------------0100: 移动公司在你打电话之前就收了你的钱,这样就省下了寄帐单的费用,并且还可以拥有一笔免息贷款。----------------------------------------------------------------------------------------------------0101: 如果在逻辑设计评审时,有两方(他们都知道自己在说什么)争论了很长时间,那么我们可以放心的认为,这一争论是无关紧要的。这些争论都很重要,但是无法解决,因为争论双方都缺乏必要的背景来做出正确的设计决策。----------------------------------------------------------------------------------------------------0102: 对已经存在的函数的面向对象封装,可以检查传递给每个函数的参数。很可能这些参数就是类的数据成员。----------------------------------------------------------------------------------------------------0103: 如果在网络中移动对象。----------------------------------------------------------------------------------------------------0104: 网络不是面向对象的。----------------------------------------------------------------------------------------------------0105: 用户界面不是面向对象的。----------------------------------------------------------------------------------------------------0106: 面向对象数据库包装器的作用就是把面向对象构造映射成关系数据库能理解的某种东西(O/R Mapping)。----------------------------------------------------------------------------------------------------0107: 不要让非面向对象的细节污染我们面向对象领域。----------------------------------------------------------------------------------------------------0108: 持久化意味着在电源被切断之后,对象可以继续存在(时间持久化)。----------------------------------------------------------------------------------------------------0109: 空间持久化是指对象并不是通过把自身保存到静态媒体上来在电源切断后延续生命,而是在监测到电源正要切断时就通过网络进入另一台安全的计算机,在那里它们可以继续执行处理,或者空闲等待。直到它们原本所在的计算机再次启动可用,那时它们再返回到原来的计算机中。----------------------------------------------------------------------------------------------------0110: 相等(值相等),相同(引用相等)。----------------------------------------------------------------------------------------------------0111: 低廉的开发成本,意味着未来更高的维护代价。----------------------------------------------------------------------------------------------------0112: 按约定编程是一个重要的错误之源。----------------------------------------------------------------------------------------------------0113: 安全浅拷贝的实现是通过引用计数实现的。----------------------------------------------------------------------------------------------------0114: 不要绕开公开接口去修改对象的状态。----------------------------------------------------------------------------------------------------0115: 发现良好的设计经验原则的方法是寻找不同领域的不同开发者所追随的趋势,如果这些趋势造就的设计表现出了我们想要的特征(例如:易于扩展,易于维护,易于理解),那么就可以把这个趋势归纳为原则。----------------------------------------------------------------------------------------------------0116: 开发者一旦意识到违反了某条经验原则,那么就可以查找一个相关的设计变换模式来解决这个问题(判断模式使用的场合)。----------------------------------------------------------------------------------------------------0117: 如果在一个对象字面范围之外的另一个对象可以改变这个对象的状态,那么维护系统的代价就会增加。这类似于类中公有数据造成的副作用,因为你不知道有多少个地方依赖这个公有数据。----------------------------------------------------------------------------------------------------0118: 若被包含的对象必须向包含它的类发送消息,包含它的类应当通过明智的使用继承来进一步泛化。这样,被包含的对象就不依赖于包含类,而只依赖于包含类的基类。让复用者从某个抽象类继承要比使用某个特定类容易得多。----------------------------------------------------------------------------------------------------0119: 大多数领域都会迫使设计者做出一些让步。----------------------------------------------------------------------------------------------------0120: 如果一个类从一个具体类继承而来,那么我们就会担心这个具体的基类会以某种派生类所不愿见到的方式作出改变。如果发生了这样的事情,那么这一架构就无法支持这一改变。----------------------------------------------------------------------------------------------------0121: 经验原则可以被看作是从一个设计模式变换到另一个设计模式的理由。----------------------------------------------------------------------------------------------------0122: 能够开发出可以指导用户把不良的设计变换成好的设计的工具呢?----------------------------------------------------------------------------------------------------0123: 开发一套模拟ATM系统作为例子。----------------------------------------------------------------------------------------------------0124: 面向对象的设计开始是数据驱动的,然后变换到行为驱动上。----------------------------------------------------------------------------------------------------0125: 对.NET类库的反汇编,可以作为扩展新控件的参考。例如:imagebutton就可以参考button类的实现代码。----------------------------------------------------------------------------------------------------0126: 经验原则很容易记忆,因为一般都很短。而模式往往都很长。----------------------------------------------------------------------------------------------------0127: 没有量化的衡量复杂度的尺度。----------------------------------------------------------------------------------------------------0128: 访问持久对象的花费总是昂贵的。----------------------------------------------------------------------------------------------------0129: 只有行为的不同才可能是继承关系。----------------------------------------------------------------------------------------------------0130: 拷贝构造函数是一个以同类型对象的引用为参数的构造函数。如果类的构造函数没有定义,编译器就会认为是以逐个成员拷贝的方式来复制数据成员。问题是复制指针被定义为将一个变量的地址复制给另一个变量。这种隐式指针复制的结果就是两个对象拥有指向同一个动态分配的内存空间的指针。当释放第一个对象的时候,它的析构函数就会释放与该对象有关的动态分配的内存空间。而释放第二个对象的时候,它的析构函数将会释放相同的内存。两次释放相同的内存是一种错误。解决的方法既可以采用深拷贝,也可以采用引用计数(浅拷贝)。----------------------------------------------------------------------------------------------------
原文链接:https://www.f2er.com/javaschema/288210.html