概要
在任何应用系统中,每一个对象都可能扮演多种角色,你在家里是父亲,在公司则可能是一个程序员,一个为你提供原材料的公司可能同时又是你的客户。。,这样的问题一次又一次的出现,我经常看到应用系统不能很好处理这些问题,在本文中,我将仔细描述这一重要的分析模式,并使用TAOERP 基本业务元素(TBCC)展示如何使用这一分析模式处理组织机构相关的问题。
一个应用系统经常需要某一个对象在不同的上下文中具有不同行为的情形,最常见的例子是客户和供应商的问题。 例子:
某制鞋企业有很多为它们提供真皮的合作公司,在处理采购订单时,这些合作公司是它的供应商,但这些合作商同时从该制鞋企业采购皮鞋,所以在处理销售订单时,这些公司又变成了它的客户。
许多建模人员在处理这类问题的时候,经常轻率地做出判断,当用户需求不能满足时,他们才发现这样的判断是不正确的。
正如Martin Fowler所言,作为一个分析模式,我在这里主要关心在何种情况下需要使用什么样的模型,而并不是太关心具体的实现如何。本文中出现的Java代码虽然来自Tao BC库,但是出于示例的目的,都进行了简化。读者也应该把主要精力放在模型本身,或者说是接口上而不是实现。
我要提醒的是,本文虽然论述了比较复杂的Role建模方法,但是读者在应用这些模式之前需要仔细考虑它们是否必要应用到你的模型之中。因为,任何一种复杂的模型虽然能够解决复杂的问题,但是不可避免地会带来额外的开销,所以,如果能够用简单的模型处理你手头上的问题,不要用更复杂的。面向对象和框架开发方法最大的好处之一就是能够在你需要的时候进行修改而对系统的影响最小。按照Kent Beck的Extreme Programming 理论:“只做你现在需要的”。当然,一旦问题发生变化,你需要用其它面向对象的方法进行Iterator,这是另外一个主题,我也许会在其它的专栏中介绍。
上下文和动机
假设我们现在要开发一个企业销售管理系统,在这样的系统中,关键的抽象之一就是合作伙伴客户,因此我们的设计模型中将包括客户Customer类。该类的接口提供对客户名字、地址、电话、Email,客户信用度等属性的操作。
现在,假设我们也需要一个采购管理系统,这时候我们需要一个供应商的抽象,尽管供应商在很多方面和Customer一样,但是譬如供应商的提前期等操作显然和客户有所不同。这是我们抽取一个不同的Supplier类的原因。
但是,当我们的销售系统和采购管理系统一起集成到供应链管理的时候,我们会发现独立抽象Customer和Supplier这样的类会碰到很多问题。一个供应商可能同时是你的客户,又或者你的一个供应商后来变成了你的客户。你也许考虑供应商和客户从一个抽象的Person类继承。
但是,这还是有问题。首先,从对象标识的角度来讲,虽然我们的Customer和Supplier继承自同一个Partner,但是他们的对象属于不同子类的实例,所以他们不可能相同。因此,代表同一个合作伙伴的Customer和Supplier的两个对象具有不同的对象标识。它们之间的相同只能通过其它的机制模拟实现。如果两个对象指代同一个实际对象,他们从Partner上继承的属性应该相同。但是,我们会在多态搜索时发生问题,如果我们搜索系统中所有的Partner,那么相同的Partner(包括、供应商、客户)可能会重复出现,我们必须小心处理这些重复问题。
角色模式把对象在不同上下文(销售系统、采购系统)相关的视图建模成Role Object,这些角色对象动态地连结到核心对象(Core Object)。这样形成的对象聚集表达一个逻辑对象,它能够处理包含多个物理对象的问题。
象Partner这样的关键抽象建模为一个接口ÿ