1. 程式人生 > >PHP設計模式(二):抽象類和介面

PHP設計模式(二):抽象類和介面

Introduction

對於程式設計來說,對事物的抽象是一個老生常談的話題,抽象問題更利於面向物件程式設計以及程式設計模式。
和C/C++,Java,Python等語言一樣,PHP也支援面向物件,但是又有略微區別,如PHP支援在介面中定義常量,但是不支援抽象變數。

抽象/Abstraction

對事物的抽象是指,區別兩個不同事物之間的本質特徵,這兩個事物應該在某個視角上有明確的區分界限。

如,鯨魚和鯉魚,這兩個事物在動物的視角上,有明確的區分界限,屬於不同的動物;但是在水生動物的視角上,他們屬於同一種動物的抽象。
合理的對問題進行抽象,構造模型,將更容易通過程式設計來解決問題。
記住:抽象是程式設計解決問題的基礎,越複雜的問題,越需要一開始就對問題進行抽象,而不是直接寫程式碼。

抽象類/Abstract Class

抽象類是一個程式設計概念,PHP中叫Abstract Classes。在設計模式中,抽象類不能夠被例項化/初始化,但是可以依靠具體類的繼承來實現。
有點抽象,對吧?用程式碼來解釋:

<?php
abstract class Animal {
  public $name;
  abstract public function eat($food);
}
?>

定義了動物這個抽象類,動物的屬性是名字name,然後有一個方法是吃食物eat food。
為什麼動物是抽象類?因為動物這個物種並不是一個存在於自然界的東西,它是人類腦海裡抽象出的東西。存在自然界的是鯨魚和鯉魚這樣的確定性動物。
比如鯨魚的概念,應該是屬於動物,繼承Animal類,我們定義鯨魚這個類以及吃東西的方法:

<?php
class Whale extends Animal {
  public function __construct() {
    $this->name = "Whale";
  }
  public function eat($food) {
    echo $this->name . " eat " . $food . ".\n";
  }
}
?>

現在我們可以初始鯨魚類,並且呼叫吃的方法了:

<?php
  $whale = new Whale();
  $whale->eat("fish");
?>

執行一下:

$ php Whale.php
Whale eat fish.

介面/Interface

PHP也支援面向過程程式設計概念中的介面,下面同樣用鯨魚的例子來講述:

<?php
interface IAction {
  public function eat($food);
  public function swim();
}
?>

同樣定義一個鯨魚類,來實現上述介面:

<?php
class Whale implements IAction {
  public function eat($food) {
    echo "Whale eat " . $food . "\n.";
  }
  public swim() {
    echo "Whale is swimming.\n";
  }
}
?>

現在我們可以初始鯨魚類,並且呼叫吃的方法了:

<?php
  $whale = new Whale();
  $whale->eat("fish");
?>

執行一下:

$ php Whale.php
Whale eat fish.

抽象類vs介面

上面的抽象類和介面的例子,看上去是不是類似?事實上,對於PHP程式設計來說,抽象類可以實現的功能,介面也可以實現。
抽象類的介面的區別,不在於程式設計實現,而在於程式設計模式的不同。
一般來講,抽象用於不同的事物,而介面用於事物的行為。
如:水生生物是鯨魚的抽象概念,但是水生生物並不是鯨魚的行為,吃東西才是鯨魚的行為。
對於大型專案來說,物件都是由基本的抽象類繼承實現,而這些類的方法通常都由介面來定義。
此外,對於事物屬性的更改,建議使用介面,而不是直接賦值或者別的方式,如:

<?php
interface IAction {
  public function eat();
}
class Whale implements IAction {
  public function eat() {
    echo "Whale eat fish.\n";
  }
}
class Carp implements IAction {
  public function eat() {
    echo "Carp eat moss.\n";
  }
}

class Observer {
  public function __construct() {
    $whale = new Whale();
    $carp = new Carp();
    $this->observeEat($whale);
    $this->observeEat($carp);
  }
  function observeEat(IAction $animal) {
    $animal->eat();
  }
}
$observer = new observer();
?>

執行一下:

$ php Observer.php
Whale eat fish.
Carp eat moss.

Summary

好的設計模式是嚴格對問題進行抽象,雖然抽象類和介面對於程式設計實現來說是類似的,但是對於程式設計模式是不同的。