新聞中心
上一篇我們介紹了設(shè)計(jì)模式的特性并且詳細(xì)講解了4種創(chuàng)建型模式,創(chuàng)建型模式是負(fù)責(zé)如何產(chǎn)生對(duì)象實(shí)例的,現(xiàn)在我們繼續(xù)來給大家介紹結(jié)構(gòu)型模式。
站在用戶的角度思考問題,與客戶深入溝通,找到鹽城網(wǎng)站設(shè)計(jì)與鹽城網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、主機(jī)域名、網(wǎng)頁空間、企業(yè)郵箱。業(yè)務(wù)覆蓋鹽城地區(qū)。
一、什么是結(jié)構(gòu)型模式?
結(jié)構(gòu)型模式是解析類和對(duì)象的內(nèi)部結(jié)構(gòu)和外部組合,通過優(yōu)化程序結(jié)構(gòu)解決模塊之間的耦合問題。
結(jié)構(gòu)型模式的種類:
適配器模式
橋接模式
裝飾模式
組合模式
外觀模式
享元模式
代理模式
1、適配器模式(Adapter)
將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另一個(gè)接口,適配器模式使得原本的由于接口不兼容而不能一起工作的那些類可以一起工作。
應(yīng)用場景:老代碼接口不適應(yīng)新的接口需求,或者代碼很多很亂不便于繼續(xù)修改,或者使用第三方類庫
代碼實(shí)現(xiàn)
name = $name; } public function getName() { return$this->name; } } //新代碼,開放平臺(tái)標(biāo)準(zhǔn)接口 interfaceUserInterface { function getUserName(); } class UserInfoimplements UserInterface { protected $user; function __construct($user) { $this->user = $user; } public function getUserName() { return$this->user->getName(); } } $olduser = newUser('張三'); echo$olduser->getName()."\n"; $newuser = newUserInfo($olduser); echo$newuser->getUserName()."\n"; ?>
注意點(diǎn):這里的新接口使用了組合方式,UserInfo內(nèi)部有一個(gè)成員變量保存老接口User對(duì)象,模塊之間是松耦合的,這種結(jié)構(gòu)其實(shí)就是組合模式。不要使用繼承,雖然UserInfo繼承User也能達(dá)到同樣的目的,但是耦合度高,相互產(chǎn)生影響。
2、橋接模式
將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立變化
特點(diǎn):獨(dú)立存在,擴(kuò)展性強(qiáng)
應(yīng)用:需要不斷更換調(diào)用對(duì)象卻執(zhí)行相同的調(diào)用方法,實(shí)現(xiàn)擴(kuò)展功能
代碼實(shí)現(xiàn)
_person = $person; } public function getJob() { return$this->_person->getJob(); } } $obj = newBridgeObj(); $obj->setPerson(newStudent()); printf("本次橋接對(duì)象:%s\n", $obj->getJob()); $obj->setPerson(newTeacher()); printf("本次橋接對(duì)象:%s\n", $obj->getJob()); ?>
3、裝飾模式
動(dòng)態(tài)地給一個(gè)對(duì)象添加額外的職責(zé)。在原有的基礎(chǔ)上進(jìn)行功能增強(qiáng)。
特點(diǎn):用來增強(qiáng)原有對(duì)象功能,依附于原有對(duì)象。
應(yīng)用:用于需要對(duì)原有對(duì)象增加功能而不是完全覆蓋的時(shí)候
代碼實(shí)現(xiàn)
_user = $user; } public function getPermission() { return$this->_user->getPermission() . $this->_special; } } //裝飾類產(chǎn)品 class JavaUserextends PermUser { protected $_special = ' java程序'; } classCPlusUser extends PermUser { protected $_special = ' c++程序'; } $user = newUser(); printf("permission:%s\n", $user->getPermission()); $user = newJavaUser($user); printf("permission:%s\n", $user->getPermission()); $user = newCPlusUser($user); printf("permission:%s\n", $user->getPermission()); ?>
大家想想裝飾和繼承的區(qū)別在哪?
如果是上面的例子,如果用繼承,是CPlusUser繼承JavaUser還是反過來呢?誰也不知道最終使用者需要哪一種。
在多層關(guān)系的情況下,裝飾是和順序無關(guān)并且隨時(shí)增加裝飾,而繼承只能是特定的順序,所以裝飾模式會(huì)更加的靈活。
4、組合模式
將對(duì)象組合成樹形結(jié)構(gòu)表示“部分-整體”的層次結(jié)構(gòu)。
特點(diǎn):靈活性強(qiáng)
應(yīng)用:對(duì)象的部分-整體的層次結(jié)構(gòu),模糊組合對(duì)象和簡單對(duì)象處理問題
代碼實(shí)現(xiàn)
name = $name; } public function getName() { return$this->name; } } class Userextends UserBaseInfo { private $login = false; public function setLogin($islogin) { $this->login= $islogin; } public function isLogin() { return$this->login; } } $user = newUser('張三'); $user->setLogin(true); if($user->isLogin()) { echo $user->getName()."已經(jīng)登錄了\n"; } else { echo $user->getName()."還沒有登錄\n"; } //組合模式 classLoginInfo { protected $user; protected $login = false; public function setLogin($user, $isLogin){ $this->user = $user; $this->login = $isLogin; } public function isLogin() { return $this->login; } } $user = newUser('張三'); $login = newLoginInfo(); $login->setLogin($user,true); if($login->isLogin()) { echo $user->getName()."已經(jīng)登錄了\n"; } else { echo $user->getName()."還沒有登錄\n"; } //部分可以更換,用繼承則不行 class Admin { protected $level; function __construct($level) { $this->level = $level; } function getLevel() { return $this->level; } } $admin = newAdmin(1); $login->setLogin($admin,true); if($login->isLogin()) { printf("級(jí)別為 %d 的管理員已經(jīng)登錄了\n",$admin->getLevel()); } else { printf("級(jí)別為 %d 的管理員還沒有登錄\n",$admin->getLevel()); } ?>
上面的例子分別展示了使用繼承和組合來處理新功能,在簡單的情況下看似區(qū)別不大,但在項(xiàng)目后期越來越復(fù)雜的時(shí)候組合模式的優(yōu)勢就越來越明顯了。
例如上面的登錄信息,如果要增加登錄次數(shù)、最后登錄時(shí)間、登錄ip等信息,登錄本身就會(huì)變成一個(gè)比較復(fù)雜的對(duì)象。如果以后有新的需求比如好友信息、用戶的訪問信息等,再要繼承的話,用戶類就會(huì)變得非常龐大,難免各父類之間沒有沖突的變量和方法,而外部訪問用戶類的眾多方法也變得很費(fèi)勁。采用組合模式后,一個(gè)類負(fù)責(zé)一個(gè)角色,功能區(qū)分非常明顯,擴(kuò)展方便。
5、外觀模式(門面模式)
為了系統(tǒng)中的一組接口提供一個(gè)一致的界面
特點(diǎn):向上抽取,有共性
應(yīng)用:內(nèi)部接口眾多,由統(tǒng)一的接口來調(diào)用
_operation = newOperation(); } public function testAll() { $this->_operation->testPlus(); $this->_operation->testMinus(); $this->_operation->testTimes(); } } //測試用例,測試全部接口 $tester = newTester(); $tester->testAll(); ?>
門面模式估計(jì)大家在實(shí)際代碼中都已經(jīng)使用到了,接口較多時(shí)把相似功能的接口封裝成一個(gè)接口供外部調(diào)用,這就是門面模式。
6、享元模式
運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度對(duì)象,采用一個(gè)共享來避免大量有相同內(nèi)容對(duì)象的開銷。這種開銷中最直觀的就是內(nèi)存的損耗。
特點(diǎn):高效性,共享性
應(yīng)用:系統(tǒng)底層的設(shè)計(jì)。例如字符串的創(chuàng)建。如果兩個(gè)字符串相同,則不會(huì)創(chuàng)建第二個(gè)字符串,而是第二個(gè)的引用直接指向第一個(gè)字符串。$str1=”abc”,$str2=”abc”.則內(nèi)存存儲(chǔ)中只會(huì)創(chuàng)建一個(gè)字符串“abc”而引用$str1.$str2都會(huì)指向它。
7、代理模式
為其他對(duì)象提供一個(gè)代理來控制對(duì)這個(gè)對(duì)象的訪問,就是給某一對(duì)象提供代理對(duì)象,并由代理對(duì)象控制具體對(duì)象的引用。能夠協(xié)調(diào)調(diào)用者和被調(diào)用者,能夠在一定程度上降低系統(tǒng)的耦合性。
特點(diǎn):低耦合性,獨(dú)立性好,安全性
應(yīng)用:客戶訪問不到或者被訪問者希望隱藏自己,所以通過代理來訪問自己。
代碼實(shí)現(xiàn)
_user = new User(); } public function getName() { return$this->_user->getName(); } } //內(nèi)部調(diào)用 $user = newUser(); printf("username:%s\n", $user->getName()); printf("usertype:%s\n", $user->getType()); //外部調(diào)用 // $user = newUserProxy(); //printf("user name:%s\n", $user->getName()); //printf("user type:%s\n", $user->getType());//不能訪問,及時(shí)知道內(nèi)部對(duì)象有這個(gè)方法 ?>
二、總結(jié)
代理模式、適配器模式、門面模式、裝飾模式的區(qū)別
相同之處:都封裝一個(gè)內(nèi)部對(duì)象,調(diào)用內(nèi)部對(duì)象的方法
不同之處:各自有各自的特性和應(yīng)用場景,不能相互替代。所以用的時(shí)候要仔細(xì)分析用那種合適。
關(guān)于模式的選用問題
模式的選用要根據(jù)實(shí)際的業(yè)務(wù)需求,通過對(duì)業(yè)務(wù)邏輯的仔細(xì)分析,再根據(jù)模式具有的特性和應(yīng)用場景進(jìn)行合理的選擇和區(qū)分。大部分情況下業(yè)務(wù)的場景決定了哪種模式,而不是選擇哪個(gè)模式去實(shí)現(xiàn)一個(gè)業(yè)務(wù),少數(shù)情況幾種模式確實(shí)都能解決問題,那主要就是考慮以后的擴(kuò)展了。
到這里我們已經(jīng)了解了7種結(jié)構(gòu)型模式,下一篇我們繼續(xù)給大家介紹設(shè)計(jì)模式的行為型模式,先預(yù)覽一下行為型模式的種類吧:
模版方法模式
命令模式
迭代器模式
觀察者模式
終結(jié)者模式
備忘錄模式
解釋器模式
狀態(tài)模式
策略模式
職責(zé)鏈模式
訪問者模式
標(biāo)題名稱:php設(shè)計(jì)模式(二):結(jié)構(gòu)型模式
文章路徑:http://ef60e0e.cn/article/gegeoi.html