在我上篇文章应用OOP的设计过程演化(一) 里,结合了实例通过应用OOP和重构等技术,你已看到代码是怎样一步一步复活的。让最初死板的代码变得灵活、可扩展,设计的不断演化过程证实,代码一步一步的复活就如同给一只冻僵翅膀的小鸟带去温暖的阳光一样。 上一篇文章虽然算得上是完美的演义了一个应用OOP的设计过程,但缺点也不少,可能因为这样给文章留下了败笔。那下面我们就来分析下这些不足之出。我们在设计中为什么要不断的抽象,重构?因为最初的设计不可能是完美的,我们不能一下子就完全把各个对象、类、接口等角色的职责划分得清清楚楚,只有通过不断的对设计进行修改才能更进一步的分清各个角色的职责。 “既然抽象销售业务的基类(Sel)l和租赁业务的基类(Hire)都具有相同的行为,这里我们完全可以在进一步的抽象,为什么不为这两个类定义一个统一的接口呢?”这是上一篇文章中留下的问题。是的,我们确实应该这么做:
此时,我们还需要修改Sell和Hire两个类,让其继承IMoney接口,如下UML图示: 此时,客户端调用就可以直接依赖于最高层抽象IMoney接口,是不是到此就画上完美的句号了呢?事实并非我们所想的那么简单,我们虽然已经抽象出了最高层次的接口,但是这样还是有所不足,那不足之处在哪里呢?解决这个问题之前我们先来分析下具体的业务逻辑。 在一个书店的业务(不管是销售还是租借业务)里,只要存在业务关系,那就存在这这样的依赖,从第一篇文章(没有阅读过第一篇文章建议先阅读完第一篇文章:《书店信息系统》系列一----应用OOP的设计过程演化 )里的设计可以看出,每完成一笔业务交易,就会涉及到顾客类型(会员、普通顾客)、交易类型(出售、出租)、租借类型(租借、归还),我们还可以为书进行分类,比如生活类,小说类以及杂志等。既然有这样的关系存在,从设计上来说我们是不能在应用中强行来指定类型的,那应该怎么做呢?我们是不是应该对业务类型进行封装?这里我采用枚举:
对也类型进行封装后,我们在次进一步的分析具体的业务逻辑,在书店业务里,每次交易是不是还存在着书名、客户(顾客)名、书的定价以及顾客所支付的现金呢?然后这些属性都是任何一笔业务交易都存在的,从对象的职责上来说,我们应该把这些属性建立在共性层次上,那是这样的吗?
应用体系设计完毕,那下面应该把全部精力投入到业务逻辑的分析上了。首先从销售逻辑出发,书店要销售出去一本书,那他首先要做的工作是什么?暴露书的属性:书名和定价还应该有买书的用户吧,其次还应该有客户所支付的现金。显然这些职责应该划分到销售书的父类(Sell)里,实际收取了多少钱这个还需要根据顾客的类型来决定具体采用何种收费策略,具体的收费策略的职责应该是具体的业务对象(Buy和SBuy)来完成,Sell作为父类,他所承担的职责是封装具体业务对象的共同属性和行为。详细如下: