幾個模式簡述:
1、工廠模式
工廠模式 是一種類,它具有為您創建對象的某些方法。
您可以使用工廠類創建對象,而不直接使用 new。這樣,如果您想要更改所創建的對象類型,只需更改該工廠即可。使用該工廠的所有代碼會自動更改。
系統某個部分中的函數和類嚴重依賴於系統的其他部分中函數和類的行為和結構。
您需要一組模式,使這些類能夠相互通信,但不希望將它們緊密綁定在一起,以避免出現聯鎖。
在大型系統中,許多代碼依賴於少數幾個關鍵類。需要更改這些類時,可能會出現困難。
2、單元素模式
某些應用程序資源是獨占的,因為有且只有一個此類型的資源。
例如,通過數據庫句柄到數據庫的連接是獨占的。
您希望在應用程序中共享數據庫句柄,因為在保持連接打開或關閉時,它是一種開銷,在獲取單個頁面的過程中更是如此。
3、觀察者模式
觀察者模式為您提供了避免組件之間緊密耦合的另一種方法。
該模式非常簡單:一個對象通過添加一個方法(該方法允許另一個對象,即觀察者 注冊自己)使本身變得可觀察。
當可觀察的對象更改時,它會將消息發送到已注冊的觀察者。這些觀察者使用該信息執行的操作與可觀察的對象無關。結果是對象可 以相互對話,而不必了解原因。
4、命令鏈模式
命令鏈 模式以松散耦合主題為基礎,發送消息、命令和請求,或通過一組處理程序發送任意內容。
每個處理程序都會自行判斷自己能否處理請求。如果可以,該請求被處理,進程停止。您可以為系統添加或移除處理程序,而不影響其他處理程序。
5、策略模式
我們講述的最後一個設計模式是策略 模式。在此模式中,算法是從復雜類提取的,因而可以方便地替換。
例如,如果要更改搜索引擎中排列頁的方法,則策略模式是一個不錯的選擇。
思考一下搜索引擎 的幾個部分 —— 一部分遍歷頁面,一部分對每頁排列,另一部分基於排列的結果排序。
在復雜的示例中,這些部分都在同一個類中。通過使用策略模式,您可將排列部分放入另一個 類中,以便更改頁排列的方式,而不影響搜索引擎的其余代碼。
常用模式詳解:
1、 單例模式(三私一公)
①、私有的構造方法 (訪問控制:防止外部代碼使用new操作符創建對象,單例類不能在其他類中實例化,只能被其自身實例化)
②、私有的靜態屬性 (擁有一個保存類的實例的靜態成員變量)
③、私有的克隆方法 (擁有一個訪問這個實例的公共的靜態方法,常用getInstance()方法進行實例化單例類,通過instanceof操作符可以檢測到類是否已經被實例化)
④、公有的靜態方法 (防止對象被復制)
所謂單例模式,也就是在任何時候,應用程序中只會有這個類的一個實例存在。
常見的,我們用到單例模式只讓一個對象去訪問數據庫,從而防止打開多個數據庫連接。
要實現一個單例類應包括以下幾點:
和普通類不同,單例類不能被直接實例化,只能是由自身實例化。因此,要獲得這樣的限制效果,構造函數必須標記為private。
要讓單例類不被直接實例化而能起到作用,就必須為其提供這樣的一個實例。
因此,就必須要讓單例類擁有一個能保存類的實例的私有靜態成員變量和對應的一個能訪問到實例的公共靜態方法。
在PHP中,為防止對單例類對象的克隆來打破單例類的上述實現形式,通常還為基提供一個空的私有__clone()方法。
下面是一個基本的單例模式:
class SingetonBasic {
private static $instance;
private function __construct() {
// do construct..
}
private function __clone() {}
public static function getInstance() {
if (!(self::$instance instanceof self)) {
self::$instance = new self();
}
return self::$instance;
}
}
$a = SingetonBasic::getInstance();
$b = SingetonBasic::getInstance();
var_dump($a === $b);
2、工廠模式
工廠模式在於可以根據輸入參數或者應用程序配置的不同來創建一種專門用來實現化並返回其它類的實例的類。下面是一個最基本的工廠模式:
class FactoryBasic {
public static function create($config) {
}
}
比如這裡是一個描述形狀對象的工廠,它希望根據傳入的參數個數不同來創建不同的形狀。
// 定義形狀的公共功能:獲取周長和面積。
interface IShape {
function getCircum();
function getArea();
}
// 定義矩形類
class Rectangle implements IShape {
private $width, $height;
public function __construct($width, $height) {
$this->width = $width;
$this->height = $height;
}
public function getCircum() {
return 2 * ($this->width + $this->height);
}
public function getArea() {
return $this->width * $this->height;
}
}
// 定義圓類
class Circle implements IShape {
private $radii;
public function __construct($radii) {
$this->radii = $radii;
}
public function getCircum() {
return 2 * M_PI * $this->radii;
}
public function getArea() {
return M_PI * pow($this->radii, 2);
}
}
// 根據傳入的參數個數不同來創建不同的形狀。
class FactoryShape {
public static function create() {
switch (func_num_args()) {
case 1:
return new Circle(func_get_arg(0));
break;
case 2:
return new Rectangle(func_get_arg(0), func_get_arg(1));
break;
}
}
}
// 矩形對象
$c = FactoryShape::create(4, 2);
var_dump($c->getArea());
// 圓對象
$o = FactoryShape::create(2);
var_dump($o->getArea());
使用工廠模式使得在調用方法時變得更容易,因為它只有一個類和一個方法,若沒有使用工廠模式,則要在調用時決定應該調用哪個類和哪個方法;
使用工廠模式還使得未來對應用程序做改變時更加容易,比如要增加一種形狀的支持,只需要修改工廠類中的create()一個方法,而沒有使用工廠模式,則要修改調用形狀的代碼塊。
3、觀察者模式
觀察者模式為您提供了避免組件之間緊密耦合的另一種方法。
該模式非常簡單:一個對象通過添加一個方法(該方法允許另一個對象,即觀察者注冊自己)使本身變得可觀察。
當可觀察的對象更改時,它會將消息發送到已注冊的觀察者。這些觀察者使用該信息執行的操作與可觀察的對象無關。結果是對象可以相互對話,而不必了解原因。
一個簡單的示例:當聽眾在收聽電台時(即電台加入一個新聽眾),它將發送出一條提示消息,通過發送消息的日志觀察者可以觀察這些消息。
// 觀察者接口
interface IObserver {
function onListen($sender, $args);
function getName();
}
// 可被觀察接口
interface IObservable {
function addObserver($observer);
function removeObserver($observer_name);
}
// 觀察者類
abstract class Observer implements IObserver {
protected $name;
public function getName() {
return $this->name;
}
}
// 可被觀察類
class Observable implements IObservable {
protected $observers = array();
public function addObserver($observer) {
if (!($observer instanceof IObserver)) {
return;
}
$this->observers[] = $observer;
}
public function removeObserver($observer_name) {
foreach ($this->observers as $index => $observer) {
if ($observer->getName() === $observer_name) {
array_splice($this->observers, $index, 1);
return;
}
}
}
}
// 模擬一個可以被觀察的類:RadioStation
class RadioStation extends Observable {
public function addListener($listener) {
foreach ($this->observers as $observer) {
$observer->onListen($this, $listener);
}
}
}
// 模擬一個觀察者類
class RadioStationLogger extends Observer {
protected $name = 'logger';
public function onListen($sender, $args) {
echo $args, ' join the radiostation.<br/>';
}
}
// 模擬另外一個觀察者類
class OtherObserver extends Observer {
protected $name = 'other';
public function onListen($sender, $args) {
echo 'other observer..<br/>';
}
}
$rs = new RadioStation();
// 注入觀察者
$rs->addObserver(new RadioStationLogger());
$rs->addObserver(new OtherObserver());
// 移除觀察者
$rs->removeObserver('other');
// 可以看到觀察到的信息
$rs->addListener('cctv');