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