组织结构的领域建模 (4): 机构类型的三种建模方式比较
从上面的几篇文章分析,我们可以得知,机构是有各种类型的。对机构类型进行领域建模,可以有三种方式:
- 没有“机构”这个共同基类的概念,为公司、部门机构类型等分别独立建模;
- 只建立机构这个具体类型,通过机构类的一个名为类型(category)的属性区分当前机构的类型是公司还是部门;
- 建立一个类型层次结构,公司和部门都是机构这个抽象基类的具体子类。
下文分别将这三种建模方式简称为“无父类”、“无子类”和“类型层级”方式,并分别比较三种方式的优缺点。
“无父类”方式
“无子类”方式
“类型层级”方式
有人也许会问:我们为什么要区分独立机构和机构单元,为何要定义公司、部门等各种机构子类,而不是统一建立一个机构类,而通过一个鉴别属性(例如orgType)表明这是一个公司还是部门?那样不是更加简单明了?
对这个问题的回答涉及到面向对象和面向过程的比较。
通过定义机构类型层级,我们可以实现下面的行为:
不同的机构子类型可以拥有不同的属性集。
例如公司可以包含工商执照号码,组织机构代码等等属性,而部门没有这些属性。
保证机构层级的合法性。例如公司下面可以设立部门和下级公司,部门下面只可以设立部门。采用上面的类型层级,我们可以在机构基类上定义createChild()方法,在当前机构下创建一个下属机构:
1 |
|
在公司类上这样实现它:
1 |
|
在部门类上这样实现它:
1 |
|
当试图在部门下创建公司时,部门类将抛出OrganizationCreationException异常。
- 保证只有独立机构才能够聘用员工。
我们可以在独立机构下定义employ()方法,由当前机构聘用员工:
1 |
|
公司、厅、局是独立机构的子类,因此可以继承employ方法,聘用员工;部门、处、室不是独立机构的子类而是机构单元的子类,因此无法聘用员工。
你可以争辩说,用一个全局的机构Organization类表示所有的机构,通过鉴别属性orgType区分机构类型也可以做到上述各点。但是实现起来复杂、笨拙,并且脆弱。
- 机构类的属性集必须是所有可能的机构类型属性集的超集,而且所有的机构类型都拥有所有这些属性。这一点使得该类非常复杂,而且部门类也拥有工商执照号码是非常奇怪甚至错误的事情。
- 机构类的行为集必须是所有可能的机构类型行为集的超集。因此,部门也拥有聘用员工、与员工签订劳务合同的资格(这一点不符合国家政策),至少在接口上看是如此。
- 为了保证机构层级和机构层级的合理性,必须在机构类内部写出大量过程式代码,充满了if…else if…或switch…case…这样的意大利面条式复杂、冗长的代码。例如:
1 |
|
- 在扩展时违反开放-封闭原则。每当添加新的机构类型时,必须对机构类做出大量的改动,以保证其行为的正确性。我们几乎需要在机构类的每一个方法上添加一段代码块,而不像面向对象的方式那样,只需要在新的子类上定义新的行为,而原有的代码丝毫不需要改动。
面向对象的方式采用分散决策的策略,将每个决策点分散到每个子类去决定;而面向过程的方式采用集中决策的策略,在基类(或过程类)上实现一切,维护一切,形成一个难于理解、难于维护、难于测试、正确性无法验证、可靠性无法保证的巨型上帝类。
充分利用面向对象的继承、封装、多态等方式,可以构造一个良好的系统。