1.3.2 行为就是动作
现在我们知道了如何用数据描述对象的状态,最后一个要学习的术语是行为(behavior)。行为是一个对象可以发生的动作。在某一类对象上可以发生的动作通过这个类的方法(method)来表达。在编程层面上,方法就像结构化编程中的函数,但它们可以访问对象的属性,也就是当前对象数据的实例变量。像函数一样,方法也可以接收参数并返回表示结果的值。
参数代表在调用方法时需要传递给方法的一系列对象。在实际调用时传给方法的对象案例通常被称为实参(argument)。这些对象被绑定到参数变量中,然后在方法体中使用,用于执行方法需要完成的任何行为或任务。返回值是任务的结果。在执行方法时可能会造成对象内部状态的变化。
我们已经给我们的“橘子苹果库存管理系统”画了基本的草图,现在继续扩展一下。对于橘子(orange)来说,一个可能的动作是pick(采摘)。想一下实现细节,pick需要做两件事:
• 更新orange的Basket属性,记录这个橘子属于某个特定的篮子。
• 更新Basket的Orange列表属性,记录在这个篮子中有这个橘子。
所以,pick需要知道它要处理哪个篮子。我们通过将Basket作为参数传递给pick方法来实现这一点。由于我们的果农同时也卖果汁,所以我们也可以为Orange类添加一个squeeze(榨汁)方法。当榨汁的时候,squeeze方法可能会返回获得果汁的数量,同时也需要将橘子从它所在的篮子中移除。
Basket类可以有一个sell(售卖)动作。当一篮水果被卖掉时,我们的库存系统需要更新一些我们现在还没涉及的对象的数据来记账或者计算利润。或者,我们篮子里的橘子可能还没卖掉就已经坏掉了,因此我们需要添加一个discard(丢弃)方法。现在我们将这些方法添加到类图中,如图1.5所示。
图1.5 带属性和方法的类图
通过给各个对象添加属性和方法,我们能够创建一个由交互的对象所组成的系统。系统中的每个对象都属于某一个类。这些类指定了对象可以拥有哪些类型的数据以及有哪些可以被调用的方法。每个对象的数据都可能与同一个类中其他对象的状态是不同的。因为对象的状态不同,所以在调用不同对象的方法时可能产生不同的反应。
面向对象的分析和设计就是为了弄清楚有哪些对象以及它们之间应该如何交互。每个类都有责任和要协作的事情。后文描述的原则,就是用来使这些交互过程尽可能简单、直观的。
请注意,销售一篮水果的动作不一定要被放在Basket类中。它也可以被放在其他某个负责多个篮子以及篮子位置的类中(图中没有画出)。我们的设计通常都有边界。我们也需要考虑如何把职责分配给不同类的问题。职责分配问题并不总是一下就分得很清楚,这使得我们不得不画多个UML图来比较不同的方案。