代码改变世界

First Head Object-Oriented Design and Analysis学习笔记(五)之下

2010-07-28 23:22  Aga.J  阅读(272)  评论(0编辑  收藏  举报

第五章 

(Part 2)

Good design=flexible software

Give your software a 30-minute workout

前言:

继续第五章Part 1留下来的问题,我们尝试解决前面吉他系统的可拓展性不足的问题。

案例分析:

案例描述:

第五章中我们发现

(1)每次增加一个Instrument类的子类时,我们就必须修改Inventory类的addInstrument函数,因为其实现是通过判断传进来的参数是否是某个具体类的instance来完成初始化操作的

(2)在Inventory类里有两个根据不同乐器具体类的search函数

(3)使用了继承的方式,完成了Guitar和Mandolin类对Instrument的继承,但是这样一来,Instrument抽象了大多数特征和方法,使得两个子类的内部属性和方法都很少

(4)每增加一个Instrument子类时都必须同时增加一个InstrumentSpec的子类

clip_image002clip_image004

问题提出:

1 对于search,是否有办法减少为只有一个函数呢,而且是通用的

问题解决:

1 书里面说因为之前的设计是把InstrumentSpec作为一个抽象类,所以无法创建一个Instrument的对象,所以只能通过下图这种方法来完成search

clip_image006而解决这个问题的思路就是we should be focusing on the interface, and not all those implementation classes.所以我们把InstrumentSpec作为一个具体类,这样一来,我们就可以使用一个接受InstrumentSpec作为参数的search函数

clip_image008

但是我有个疑问就是将Instrument抽象为一个抽象类,不就是恰恰可以使用将它作为具体类的这个功能吗?或许这里作者说错了,但是他的解决方案是正确的,我们要focus on the interface,而不能绑定在implementation classes。通过这种方式,类比C++的基类指针指向派生类对象的思想,我们让我们的代码有了很高的自由度,而不会被束缚在某个implementation class

问题提出:

1 Instrument类确实是封装了许多乐器的共有特性,但是每个子类都仅仅有自己的构造函数而没有其他行为或者属性

问题解决:

1 必须明确一点是,创建子类的原因是因为他和基类有不同的行为,而在这个吉他系统中,子类的行为和Instrument基类的行为或者说和其他子类的行为并没有不同点,不同的仅仅在属性。他们behave the same(如果我们的系统是关于乐器的演奏方式,那么就会有play的行为上的不同,但是在销售环境下,卖吉他和卖曼陀林都一样),这个时候想一想我们能通过“inheritance”,“polymorphism”,“abstraction”,“encapsulation”这OO的四大特性怎么来让我们的系统变得更灵活一点,我们发现“encapsulation”,之前说过他不仅可以把一些重复的代码封装起来,而且还能封装what varies,就是把容易变化的代码也封装了。我们在前面只是将IntrumentSpec从Instrument中封装剥离出来,但是我们并没有把InstrumentSpec里面经常变化的属性成员封装出来。

这样一来,我们可以试着删除从Instrument继承的子类,因为那些类复杂且多,只是提供xxxSpec类就可以了

clip_image010

然后通过增加一个InstrumentType(这里有点像玩家和角色的设计模式),Instrument不一样的只是他们的InstrumentType,其他基本属性和行为都是一样的

clip_image012

接下来就按照原先想的那样,不仅encapsulate the specification common across clients requests and instruments from Instrument class,还要encapsulate the properties that vary from the InstrumentSpec Class

而封装那么多属性的方法就是使用一个集合类,利用了“名称/值”的思路,进行属性的保存,而且是动态的保存

clip_image014

clip_image016

Important Point

1 higher cohesion can really help your coupling.

2 clip_image018

3 when you have a set of properties that vary across your object, use a collection, like a Map, to store those properties dynamically. You will remove lots of methods from your classes, and avoid having to change your code when new properties are added to your app.

4 cohesion measures the degree of connectivity among the elements of a single module, class, or object. The higher the cohesion of your software is, the more well-defined and related the responsibility of each individual class in your application. Each class has a very specific set of closely related actions it performs

5 the higher the cohesive in your application, the better defined each object’s job is. And the better defined an object is, the easier it is to pull that object out of one context, and have the object do the same job in another context. The object is happy to just keep on doing its very specific job, no matter where it’s being used.

6 once you’ve got functionality down , move on to making good design decisions, using solid OO principles to add flexibility.

7 class are about behavior and functionality(所以不能一味的继承,要看是否和父类或者其他子类有没行为上的不同)

小结:这一章给出了解决方案,是个很好的例子,但是现实中谁又能像这样的开发一个系统呢,谁又考虑到如此的细致呢?