在上一篇里面,我们初步了解了OO设计,OO设计的最独特之处在于他看待需求的方式。用这样的方式 ,我们不需要急于确定软件需要实现哪些流程、设计哪些功能点、制作哪些画面,而是要关注需求中一 些更加基本的概念。首先根据这些概念开发出一些零件,然后把这些零件组装起来实现需要的功能。用 这样的方式,我们不需要一开始就去知道所有的业务需求,只需要知道一些比较重要的需求,就可以开 始开发了。这样开发出来的程序不仅可以实现当前的需要,同时也是一个业务开发的平台,在这个平台 上可以不断的开发新的功能。
这种设计思想有很多实际的例子,比如Microsoft Office。下面的 图就展示了Excel里面最基本的几个对象:
Excel的各项功能都是建立在这个对象模型基础上的。比如要实现设置字体 的功能,就可以这样编写:先打开一个字体对话框,使用者选择字型、字号,然后把这个字体设置到区 域上:
Font font = CommonFontDialog.ChooseFont();
Application.ActiveWorkbook.ActiveSheet.Range("A1").Font = font;
Excel还把这些对象的引用暴露给了脚本引擎,于是我们就可以使 用VBA调用他们,实现我们自己想要的各种功能,这就是Office宏。我们可以编写一段VB脚本,把鼠标选 中区域的单元格复制到另一个工作表中,然后把某一个的单元格的值赋值为一个公式,计算出我们需要 的数值。Excel不仅本身是一个好用的制表工具,他更是一个强大、易用的开发平台。使用者可以随时根 据自己的想法,开发出需要的功能。一些大型的软件系统都是具有这样的特点,一开始就明确所有的功 能需求是不可能的,重要的是形成一个业务开发的平台,提供一些业务编程接口,在这个平台上就可以 不断的开发出新的功能。这样的开发方式不使用OO设计是很难实现的。
软件的第一个维护者和第 一个使用者就是开发者本人,因此,开发迅速、功能灵活、维护简单——这些特点在精心设 计的软件中经常是同时具有的。
运用OO方法设计程序的时候会遇到的这样困难:我们从需求中发 现了一些模糊的概念,但是怎样才能根据这些概念建立合理的对象模型呢,到底哪些概念应该是一个类 ,哪些概念只应该是一个方法和属性,这些类之间应该是什么样的关系?要解决这个问题,最根本的途 径当然是尽量深入的了解需求(比如说翻翻会计原理,看看应收款未收和已收的时候应该如何记账,其 中一个记账原则也许就是一个重要的对象;协助用户做一个供电方案,随手画出的草图,或者某个计算 公式就是一个重要的对象)。在解决了一个个困难之后,有人总结了经验,形成了一些解决特定问题的 固定套路,这样的套路就是设计模式。
有些设计模式和OO没有什么必然的关系,比如层次模式, 消息模式。但是大部分设计模式都是在OO设计中形成的,这些模式可以帮助我们发现系统中的对象、设 计对象之间的关系。了解这些模式可以帮助我们把软件设计的更加合理。并且,在探索需求的过程中, 我们也可以从模式中得到一些启发,获得设计的灵感,发现需求的真实面貌。
在上一篇我们看见 了“费用”这个类型:Fee,其实这就是一个简单的设计模式:组合模式(Composite)。这 个类的结构如下:
Fee类型是他本身的一个聚合,可以使用 GetChildren方法得到某个费用包含的其他费用。如果一个费用没有包含其他费用,他的金额就是由他自 己确定的,否则就是由他包含的费用相加确定的,这两种情况对外界提供的都是相同的方法:GetValue 。这样,我们想显示一个账单费用的时候,不用再去判断他是否包含了其他的费用,调用起来就简单了 很多。组合模式很好的体现了账单费用的层次包含关系。
刚才的情况里面,聚合类和元素类都是 同样的类型。也有些情况他们分别属于不同的类型。比如一个企业,他的营销网络是由下面一些元素组 成的:公司,市场部,直销店,代理商,自由代理人,营业员。如同下面的情况:
公司按照行政区域建立了多个市场部,市场部建立了自己的直销店,同时也 与很多代理商和独立代理人进行合作,直销店和代理商雇用了营业员。每天公司需要对每个销售网点的 情况进行查询和分析,需要知道他们定下了多少订单、收了多少货款、发展了多少新的客户。
这 是一个比较复杂的结构关系,网点类型比较多,他们的销售方式差异很大,各类数据统计的方式也不同 。并且在统计一些数值的时候,需要把下属网点的数量加起来,再加上自身的数量。如果采用组合模式 ,就可以解决这种问题。