搜尋此網誌

2012/04/27

抽象化 - Abstraction

抽象化 - Abstraction

抽象化是物件導向的精髓,以下談談抽象化...

抽象(Abstraction)是複雜概念,程序,或真實世界的一種簡化或是模型化。身為人類
的我們必須依賴抽象化才能生存。就像我們從來不會去瞭解電腦、電視等設備內部的細
節,我們看待這些設備的方式是抽象的,我們只是把它們視為一種可以提供某些服務的
東西而已。也因為如此,這些設備的廠商可以自由實作其內部機制,只要留下一個介面
(如: 遙控器)給我們即可。

而在物件導向中,抽象化是其精髓。藉著抽象化,多型才能發揮到極致,才能將系統的
變動隔絕於外。藉由抽象化,程式碼不會與特定型態的物件產生太緊密的耦合,如此才
能允許我們容易更動特定物件的的實作部分。

舉個例子來說,假設我們有一個函式 foo,它會要求車子物件行駛,但是車子有許多種,
其內部行駛的機制都不盡相同。如果我們為每一種車子寫一個函式,看來好像是物件導
向的寫法,雖然一些語言都支援函式overload,但是此後我們必須一直維護這個函式,
只要新的車子種類加入,我們就要加入一個overload的foo函式。

void foo(ToyotaCar car) {}
void foo(NissanCar car) {}
void foo(BensCar car) {}


這個例子的缺點就是抽象化不夠,系統設計模擬真實世界太過頭了。在物件所處的虛擬
世界中,與真實世界不同的是,所有的物件都是「活的」。較好的設計應該善用抽象化
,先定義一個抽象類別 Car,用以表示車子所共有的概念,然後加入一個抽象方法 run
讓子類別override,如此foo函式永遠將特定的車子視為 Car 來處理,而不需要理會它
是那一種車子,這是否與我們只會按電源來啟動電腦,而不會去理會我們正在使用那一
廠牌那一型號的電腦一樣。

abstract class Car {
    // Concrete subclass SHOULD override this.
    abstract void run();
}

class ToyotaCar extends Car {
  void run() {
      // Do something...
  }
}

class NissanCar extends Car {
  void run() {
      // Do something...
  }
}

class BensCar extends Car {
  void run() {
      // Do something...
  }
}

void foo(Car car) {
    car.run();
}
此後我們即可用以下的方式呼叫 foo: foo(new ToyotaCar());foo(new NissanCar());foo(new BensCar()); 注意,不論我們傳入什麼車種,foo 皆可運作,只要傳入的是 Car 的子類別即可。 你是否已體會到了抽象化的精神呢?沒錯!只要我們小心規劃抽象的介面,很容易就可 以將一些變動隔離出來。後來即使加入程式碼,也不會干擾到現存的程式碼。

沒有留言: