面向对象设计(OOD)思想——还是以播放器为例(ZT) NDmTxW#g
\dq}nOsX*
有了思想才能飞翔,缺乏灵活就象少了轮子的汽车,难以飞奔。为了更好的理解设计思想,结合一个尽可能简洁的实例来说明OOD、设计模式及重构。通过下面的代码,详细地阐述面向对象设计思想。 l<89[{9o
一、传统过程化设计思想 FA+'E
假定我们要设计一个媒体播放器(只从软件设计的角度,不涉及硬件)。该媒体播放器目前只支持音频文件mp3和wav。按照结构化设计思想,设计出来的播放器的代码如下: {hE\ECT-
public class MediaPlayer =/|2f; Q
{ U^xz>:~
private void PlayMp3() npJyVh47
{ 3Dm`8Xt
MessageBox.Show("Play the mp3 file."); 7M#irCX
} )PU_'n=>
` !JcQ'u
private void PlayWav() #cZ<[K q6
{ [5iBXOmpS=
MessageBox.Show("Play the wav file.");
/uyZ[=5
} 2brxV'tk
|#)S`Ua1
public void Play(string audioType) {FrcpcrQa
{ %]iDhXLr
switch (audioType.ToLower()) g aq"+@fH
{ -q8R'?z[
case ("mp3"): k4AF
.U`I
PlayMp3(); Pf 4b/w/
break; wB~5&:]jr
case ("wav"): tr<iFT}C
PlayWav(); ?JinX'z
break; qi&;2Yv
} C.& R,$
} BbV @ziL
} d7*fP S
从传统的过程化设计思想来看,这是一段既实用又简洁的代码。 Rl%?c5U/$
如果,客户又提出新的要求:要播放器不仅仅播放mp3和wav文件,还要播放其他音频文件如wma、mp4等,为此我们要不断地增加相应地播放方法和修改条件语句,直止条件语句足够长。 nKO4o8js{{
如果,客户感到这个媒体播放器功能太少了,只能闻其声,不能见其人,太单一。如果在听着优美音乐的同时又能看到歌唱者潇洒、英俊的舞姿那就更好了。从代码设计的角度看,他们希望媒体播放器支持视频文件了。也许你会想,不会再增加视频这方面的代码,可以,在增加视频媒体的播放方法,在修改条件判断语句,如果还有其他,还可以同样地增加、修改。到此你也许会提出,要是不修改或很少修改原来的代码就能增添其他功能该多好啊! Cd"cU~HAB
这样看,原来的软件设计结构似乎有点问题。事实上,随着功能的不断增加,你越来越发现这个设计非常的糟糕,因为它根本没有为未来的需求变更提供最起码的扩展。为了应接不暇的变更需求,你不得不不厌其烦地修改原来的代码,使其适应需求变化,甚至在修改代码时,由于过多的代码依赖关系弄得人焦头烂额,直止一塌糊涂。 6^'BhHP
二、面向对象设计思想 &azy1.i~
还是以设计一个媒体播放器为例,设计要求相同。不访我们换个设计思路利用面向对象设计思想(OOD)来做做看如何! _@gd9Fi7J
根据OOD的思想,我们应该把mp3和wav分别看作是两个独立的对象。代码设计如下: 9CxFj)#5F
public class MP3 V/8"@C
{ DUAI
public void Play() _!} L\E~
{ gZ^'hW-{
MessageBox.Show("Play the mp3 file."); p;Lp-9H\33
} Hkv4^|
} .wb[cCUQ
S]O0zv^}
public class WAV a9"1a'
{ KcK,%!>B
public void Play() k|SywATr
{ ~kJ}Z<e
MessageBox.Show("Play the wav file."); |k:ecw
} bRhc8#kw)
} REj<2Lo
MKr)6PG,
Public class MediaPlayer 0[O ."9
{ 6N<v&7cSB
switch (audioType.ToLower()) 2j UEL=+Y
{ FD+y?UF
case ("mp3"): \?VNr2
MP3 m = new MP3(); [2 yxTK
m.Play(); sb3k? q
break; y-/,,,r
case ("wav"): l0&Y",vy
WAV w = new WAV(); u5 1%~
w.Play(); 1e'Ez4*
break; jk\04k
} NO%x
2dx0
} 3`mM0,fY
现在我们重构代码,建立统一的Play()方法,(在后面的设计中,你会发现这样改名是多么的重要!)更改媒体播放类MediaPlayer的代码。如果这样的设计代码,实质上没有多大的变化,只是对原来过程化设计思想的一种替代,并没有击中要害,亦然没有灵活性、可扩展性。 ]((Ix,ggP
2.1单向分派技术的应用(在这里用类的多态来实现的) *>#mI/#}
我们不访这样设想:既然mp3和wav都属于音频文件,都具有音频文件的共性,应该建立一个共同的AudioMedia父类。 'Wv`^{y <^
public class AudioMedia ;L{#TC(]J]
{ EW:tb-%`
public void Play() _>LI[yf{
{ V(5=-8k
MessageBox.Show("Play the AudioMedia file."); |RA|nu
} qIC9L"I
} WC pCWtmy
现在引入继承思想,OOD就有点雏形了(不是说有了继承就有了OOD思想,这里只是从继承的角度谈一谈OOD思想,当然从其他角度如合成、聚合等角度也能很好地体现OOD思想)。 L#}HeOEi[
其实在现实生活中,我们的播放器播放的只能是某种具体类型的音频文件如mp3,因此这个AudioMedia类只能是音频媒体的一个抽象化概念,并没有实际的使用情况。对应在OOD设计中,既这个类永远不会被实例化。为此我们应将其改为抽象类,如下: \@KK X
public abstract class AudioMedia
el"XD"*
{ Hx|<NS0}_
public abstract void Play(); yltzf
#%
} |_A DG
l)m]<EX
public class MP3:AudioMedia $OAak
{ 0Gr ^#`
public override void Play() "{lw;AA5F
{ VOY#Y*)g
MessageBox.Show("Play the mp3 file."); (=/%_jj
} }R\9ybv
} l?rT_uO 4
*Bj7\8cKC
public class WAV:AudioMedia nB+UxU@
{ 97]$*&fH
public override void Play() qVidubsW
{ I.qP$ j
MessageBox.Show("Play the wav file."); ?vd_8C2B
} y. A]un1
} uK_R#^
,Q2?Z:l
public class MediaPlayer OZ9ud ]@\
{ s&