1.1.4.3 設計模式
設計模式,以GOF為權威的那套有23種,雖說設計模式是語言無關的,但是很多偏門的設計模式基本還是在java中用的比較多
分類
第一部分建造類,很好理解,就是例項化或者提供物件。
第二部分和也比較好理解,好多是包裝一個物件,第三部分有一些就不是很好理解了,這得結合使用場景來看,不然光看這個概念是會非常枯燥的。
1建造類
1.0簡單工廠
class Mysql{
}
class Sqllite{
}
class Factory{
public static function getDb($type){
switch($type){
case 'mysql':
return new Mysql();
break;
case 'sqllite':
return new Sqllite();
break;
}
}
}
//客戶端
$db = Factory::getDb('mysql');
複製程式碼
- 就是很簡單
- 優點是簡單
- 缺點是要增加資料庫種類就要改程式碼,擴充套件性不好,違反開閉原則。
1.1工廠
interface Factory{
public static function getDb();
}
class MysqlFactory implements Factory{
public static function getDb(){
return new Mysql();
}
}
class SqlliteFactory implements Factory{
public static function getDb(){
return new Sqllite();
}
}
//配置檔案
//$dbfatory=MysqlFactory
//客戶端
$db = $dbfatory::getDb();
複製程式碼
- 1加了一個層級,2將變數用配置檔案形式提出,是簡單工廠的升級版,是常用,實用的一個設計模式
- 優點是 符合開閉原則,擴充套件性好
1.2抽象工廠
- 程式碼太複雜了,不寫了
- 工廠模式的工廠,是有一個介面和各個實現兩層,抽象工廠是給產品給建立了這樣的兩個層級,然後就是(工廠X產品)2個維度,產品有幾種是寫死的,工廠可以增加,大概就是這樣,適用於複雜情況
參考
- 計模式:簡單工廠、工廠方法、抽象工廠之小結與區別
- php設計模式(五)抽象工廠模式寫的比較複雜....
1.3單例
記住 三私一公
class Fcactory{
private static $instance = null;
private fucntion __constructe(){}
private fucntion __clone(){}
public fucntion getInstacne()
{
if(empty(self::instance)){
self::instance = new Test();
}
return self::instance;
}
}
//客戶端
$obj1 = Factory::getInstance();
$obj2 = Factory::getInstance();
echo $obj1 == $obj2?1:0;
複製程式碼
單例模式是,最最常用的模式了,也非常有特點,非常容易識別,基本操作。
1.4原型
原型模式就是複製物件,在java體系內,要單說,但是php環境,自帶的魔術方法__clone()
就解決了.....
為何要複製物件而不是重新new呢?1種情況是,要複製當前狀態而不是new出來的初始化狀態了,另一種情況是,複製比new效率高。不展開說了。
1.5建造者
有三層,產出複雜的組裝物件,組裝類 建立類 產品類。是一種複雜的情況。我覺得我2周後就會忘記....
參考設計模式的應用場景(3)--建立者模式示例程式碼是java
建造類總結
- 三個工廠的區別要搞清楚,其實還是比較好理解的簡單工廠、 工廠方法、 抽象工廠 之小結與區別
- 單例模式很好理解吧
- 建造者在php中好像比較少見,瞭解就好
- 相比結構和行為類,建造者的設計模式其實算簡單的
2結構類
2.1裝飾器
很好理解,要點是
- 要裝飾器和本體要繼承一個介面,從而保持對外的一致性
- 裝飾器接受一個本體例項,進行屬性的裝飾
看鬱冬的博文或者白俊遙的文章都能理解,這個模式白俊遙寫的比較好。
2.2介面卡
也很好理解,要點
- 輸入原物件,包裝後跟原物件保持一致
- 在包裝器額外寫一個轉換邏輯
看白俊遙和鬱冬的,很清楚
2.3代理
跟介面卡差不多,但是介面卡的重點在於,輸入原物件,轉換加工。而代理的重點在於,隱藏原物件,增加中間控制。 代理模式在java中,有其他應用,這個php弄不出來,瞭解就好,看設計模式的應用場景(8)--代理模式
裝飾器 介面卡 代理總結
都是對一個物件的包裝,裝飾器側重功能增強,介面卡側重轉換為目標格式,代理側重增加中間控制。
2.4外觀
- 雖然叫外觀,也叫門面,但是我覺得一點也不貼切,其實是把某個動作提出來,放到一個類,來解耦。
- 優點是對外變得簡潔,避免暴露內部資訊和複雜邏輯。
- 裝飾器,介面卡,代理是對一個物件化的包裝,而外觀是對一個或多個物件的包裝。
- 缺點,不好修改
看php設計模式(十五)外觀模式和設計模式的應用場景(6)--外觀模式
2.5橋接
有兩個維度可以變化,客戶端來輸入兩個變數進行組合。 鬱冬 資訊型別X速度兩個維度 白俊遙 圖案X顏色兩個維度
2.6組合
組合模式應該叫樹形模式,非常有特點,跟單例一樣容易識別,就是樹形結構,總體跟部分是一致的結構。
比如檔案系統,無限極分類,遊戲裡的作戰單元。
2.7享元
享元模式叫flyweight,我嚴重懷疑是叫share!
享元模式是為了避免例項化太多類來佔用記憶體,怎麼避免呢?就是維護一個物件池,來複用。
結構類總結
- 三個包裝模式 裝飾器 介面卡和代理,都比較好理解
- 外觀模式,是對多個物件的包裝,或者對一個操作,一個子系統的包裝,是實用的模式
- 橋接是兩個維度的變化,我沒用過
- 組合是樹形結構,跟單例一樣容易識別
- 享元是物件池,複用
3行為類
3.1觀察者
觀察者是非常著名,實用,也不難理解的模式,看程式碼就明白了
//主體介面
interface Subject{
public function register(Observer $observer);
public function notify();
}
//觀察者介面
interface Observer{
public function watch(){;
}
//主體
class Test implements Subjetc{
private $observers = [];
public function register(Observer $observer){
$this->observers[] = $observer;
}
public function notify(){
foreach($this->observers as $v){
$v—>watch();
}
}
}
//觀察者1
class Dog implements Observer{
public function watch(){
echo 'dog is copy!';
}
}
//觀察者2
class Cat implements Observer{
public function watch(){
echo 'cat is copy!';
}
}
//客戶端呼叫
$main_subject = new Test();
$main_subject->register(new Dog());
$main_subject->register(new Cat());
$main_subject->notify();
複製程式碼
3.2訪問者
我個人覺得跟抽象工廠的結構有點類似。 看這個程式碼示例PHP設計模式--訪問者模式
3.3責任鏈
責任鏈一句話就能說清楚,就是加強版的switch-case,鬱冬的例子不錯
3.4策略
策略模式的要點有
- 有主體和平級的選項,
- 可以切換選項
- 重點在於選擇
3.5命令
三個角色,命令發出者和執行者,以及命令,跟橋接有點像,也是兩個維度變化,中間一個物件耦合,但是橋接是在客戶端呼叫耦合,看白俊遙的例子
3.6模板
模板模式是定義好主體格式,而子類是隨便替換的,白俊遙有例子
3.7直譯器
我理解為是模板的一個特例
策略 模板 直譯器 總結
這幾個的共同點是,有選擇,有平級備選
- 策略的側重是選擇的靈活性
- 模板的側重是,框架是確定的,子類是可替換的
- 直譯器就是一種模板,框架的主要方法就是翻譯,子類
3.8調停者
兩個維度組合,但是不在客戶端輸入變數,而是引入第三方類來處理
3.9迭代器
php自帶迭代器
3.10備忘錄
php自帶__toString
3.11狀態
總結
我個人有一些分類
參考
- 鬱冬常用設計模式詳解 這跟我這篇一樣,是一文總結全部設計模式,型別不全,但是常用的都有,例子很精煉,非常好
- 白俊遙部落格的設計模式系列文章白俊遙的文章質量不錯,內容詳實,圖文並茂,是非常好的入門
- zhi_fu的部落格java程式碼
- 姜海強大話設計模式筆記
- php設計模式那本書