和女人类了。
从以上例子来看, 类的设计和表的设计, 不是说一定要有必然的联系。 因为既然我们写了非存取的代码, 就说明我们除了可以记录下来的特征, 还关心其它的非可固化性质的行为, 那么我们如何设计类、 对象, 则必须从这些行为以及系统中各个对象交互的视角上出发, 而不是考虑我们的表如何设计的。 注意, 这不是说我赞成以实体类去设计表, 关系模型关心和表现的是事情的另一个侧面, 所以设计表恰恰不能从对象设计倒回去。 它们之间应该是正交的, 不要存在一个依赖另外一个这样的耦合。 如何让他们兼容, 需要且应该做额外的工作。
当上面的例子简化到一定地步, 比如 if(男) else 时, 我们也不需要什么策略的对象或者类, 有一些用于体现策略脚本处理即可。 到了这个地步, 我们也许一个实体类都不需要有。 我们就简单的把系统看作根据具体情况作出判断和处理的策略系统就可以了, 这时候我们需要的仅仅是信息的载体, 这就是为什么我经常会说, 当产生了贫血对象后, 我们要考虑的不是把它变复杂, 而是看看能不能把它从系统中抹去的原因。 很多时候, 贫血类比起一个通用的信息载体, 除了字段和属性强类型的好处, 仅仅发挥一个自身标识的作用; 但是当我们调用“人能做的事情静态帮助类.上厕所(信息载体)”的时候, 实际上我们已经隐式的传递了这个标识; 我们也可以设置一些具体的手法, 保证安全。
总结:
最后, 我们再来看看这些区别, 强化一下印象:
1. “人能做的事情.上厕所(信息载体)”、“人.上厕所()”和“人.上厕所(策略)”之间如何取舍, 在于复杂度, 复杂度上升到一定程度, 我们要采取后者; 这是为了避免前者“上厕所”这一Rotine其内部复杂度上升的太高, 或者被频繁修改。 另外一个更明确的判断点在于, 人是否带有可变化的状态; 上厕所这件事是否有很多的方式。
2. 假设我们采取了含有“人”这一样一个概念的具体表达的设计, 人这个接口如何保持稳定是我们要注意的。 比如“上厕所”这一行为隐含的变化, 或者又增加“吃饭”等行为, 都属于接口的不稳定, 如果这种不稳定在短期内就会出现, 我们应该把行为和规则外包给其它概念, 而不是让它们依附在人之上。 如果我们一出生就是狼孩, 本来我们也不会具有这些概念所指的行为; 并不是说“主语.谓语”, 这样的设计方式就是合理的。
3. 我们是否需要“男人”、“女人” 或者 “讲师”、 “教授” 这样的继承体系, 可以这样判断: 必须共性大、同时差异也大。 组合比继承好, 这是从95年《设计模式》以后被大家广泛接受的原则。 很显然, 共性和差异同时非常大的情况不是特别多见。 也许我们平时见惯了我们的
aspx页面继承于Page, Page又继承于TemplateControl和Control。 且不说合理与否, 这并不能说明需要继承的情况很多。 因为这样一个继承, 使用了10000遍, 它其实还是一个继承。
4. 表设计和对象设计是两码事, 要按照各自的特点来做; 同时追求两边的合理性, 要付出的代价就是多做中间工作, 这些上面说的比较详细, 就不多说了。唯一可以说的是, 在成本上考虑, 我们要做好折中的选择。 更多的则是, 无论哪个设计, 无论什么设计方法, 我们别想太多, 更多的要找出我们关心的全部内容, 而不要把在现实生活中的知识带入过多; 因为对我们要解决的问题所在视角, 这些知识可能就成了不必要的偏见, 或者至少像用大学物理解释初中物理题。
这些问题其实在
学习面向对象以后, 做类似的信息管理时, 非常普遍。 我想你先问问自己, 你自己想采用什么样的设计呢? 其次, 看看自己能不能找到