公司最近項目不忙,午間小憩以後,小二找到C哥攀談了起來。php
"C哥,忙啥呢?"
"也沒忙啥,就是隨便看看。"設計模式
"哦哦,我最近也不怎麼忙。你上次給我講的工廠模式,受益不淺啊!"
"哈哈,是嘛!其實你不知道,還有抽象工廠模式呢!"函數
"抽象工廠模式?願聞其詳。"
"好,反正最近也不忙,就給你講講吧。"spa
"小二,你知道,奧迪A4與A6,他們使用的輪胎與燈泡是不同的。"
"是,型號不同,輪胎與燈泡確定不同。"設計
"假設如今須要製造A4與A6的輪胎和燈泡,你會怎麼寫代碼?"
"這個嘛,好寫!"code
小二熟練的打開電腦,揮斥方遒,迅速的寫出了代碼。對象
<?php class Client{ //根據不一樣型號生產不一樣輪胎 public function produce_wheel($type){ switch ($type){ case 'A4': $obj=new AudiA4Wheel(); break; case 'A6': $obj=new AudiA6Wheel(); break; default: throw new Exception('no instance found'); } $obj->produce_wheel(); } //根據不一樣型號生產不一樣燈泡 public function produce_light($type){ switch ($type){ case 'A4': $obj=new AudiA4Light(); break; case 'A6': $obj=new AudiA6Light(); break; default: throw new Exception('no instance found'); } $obj->produce_light(); } } $client=new Client(); $client->produce_wheel('A4'); $client->produce_light('A4');
"C哥,大致就是這麼個思路。您看看對嗎?"
"嗯,這代碼確實也實現了功能,可是,有問題。"接口
"有問題?什麼問題?"
"你這代碼存在着低內聚、高耦合的問題,很差維護啊。"圖片
"怎麼低內聚、高耦合了?"小二一臉茫然。
C哥鎮定自若的解釋道:
好比,如今我要增長奧迪的型號A8,那你代碼裏的函數produce_wheel()
與produce_light()
是否是都要改?也就是這兩個函數是相互依賴的,不可能用A6的輪子,而用A8的燈泡。相互依賴,是爲高耦合。rem
produce_wheel()
與 produce_light()
函數,這兩個函數都關心本身須要什麼型號的產品,而且都負責把相應的產品生產出來。也就是,他有兩個職責:關心型號、根據不一樣型號生產出對應的產品。但這兩個職責是毫無關聯的,沒有半毛錢的關係。職責過多且分散,是爲低內聚。
"C哥這麼一說,還真是這麼回事。"
"哈哈,低內聚高耦合的代碼也能實現需求,可是這樣的代碼很差維護。"
"嗯嗯,C哥,有啥好辦法嗎?"
"固然有了,咱們這裏就用到了抽象工廠模式。"
"根據我多年的經驗,出現switch語句的地方,每每意味着須要抽象、或者存在着放錯責任的地方。"
"寶貴的經驗,記下了!"
"小二,其實這裏,就是放錯了責任。"
"嗯,怎麼說呢?"
"Client端既關心如何建立對象,又關心如何用對象來製造輪子、燈泡。"
"是,他的責任太多了。"
"其實,Client端只負責使用對象製造相關產品就好了。他不用負責創造對象。創造對象,交給Client端來作,就是放錯了責任。"
"對,確實是這樣。"
"還記得前幾天給你講的工廠模式嗎?工廠模式也是爲了解決這個問題。"
"記得記得,工廠模式也是爲了實現責任的分離。"
"工廠模式針對一種產品提供一個工廠類,而抽象工廠模式是針對一組相關或相互依賴的產品提供一個工廠類。"
"那抽象工廠模式就是工廠模式的升級版本啦!"
"是的。在這裏,Client端負責向Factory發出請求,Factory返回相關對象,Client端再根據Factory返回的對象,製造相關的產品。"
"也就是Client負責使用對象,Factory負責建立對象!"
"是的,小二很聰明嘛!看看抽象工廠模式的類圖吧!"
"好的,C哥。"
"小二啊,跟你講了這麼多,接下來就看你了!"
"好的C哥,我立刻畫出類圖、寫出代碼。"
小二仿照着C哥的類圖,又畫出了用抽象工廠解決上面問題的類圖。
畫好類圖,代碼也就好寫了!
<?php //燈泡產品接口 interface Light{ public function produce_light(); } //奧迪A4燈泡產品 class AudiA4Light implements Light{ public function produce_light() { echo "AudiA4 Light produced!\n"; } } //奧迪A6燈泡產品 class AudiA6Light implements Light{ public function produce_light() { echo "AudiA6 Light produced!\n"; } } //輪子產品接口 interface Wheel{ public function produce_wheel(); } //奧迪A4輪子 class AudiA4Wheel implements Wheel { public function produce_wheel() { echo "AudiA4 Wheel produced!\n"; } } //奧迪A6輪子 class AudiA6Wheel implements Wheel { public function produce_wheel() { echo "AudiA6 Wheel produced!\n"; } } //工廠接口 interface Factory{ public function CreateWheel(); public function CreateLight(); } //奧迪A4工廠 class A4Factory implements Factory { public function CreateWheel() { return new AudiA4Wheel(); } public function CreateLight() { return new AudiA4Light(); } } //奧迪A6工廠 class A6Factory implements Factory { public function CreateWheel() { return new AudiA6Wheel(); } public function CreateLight() { return new AudiA6Light(); } } //客戶端調用類 class Client{ //運行主函數 public static function main($type){ $reflection=new ReflectionClass($type.'Factory'); $factory=$reflection->newInstance(); self::run($factory); } //生產產品 public static function run(Factory $factory){ $wheel=$factory->CreateWheel(); $wheel->produce_wheel(); $light=$factory->CreateLight(); $light->produce_light(); } } Client::main('A6');
"嗯嗯,小二不錯嘛。簡單工廠、工廠方法、抽象工廠模式,你都掌握了。"
"哈哈,感謝C哥的教導!"
"恭喜你在設計模式打怪升級的道路上,再次斬獲新技能!"
聽到這句話,小二內心美滋滋的,嘴角露出了得意的微笑......
轉載聲明:本文首發於自公衆號「聊聊代碼」,搜索「talkpoem」便可關注。
關注「聊聊代碼」,讓咱們一塊兒聊聊「左手代碼右手詩」的事兒。