PHP設(shè)計(jì)模式(三)建造者模式Builder實(shí)例詳解【創(chuàng)建型】
本文實(shí)例講述了PHP設(shè)計(jì)模式:建造者模式Builder。分享給大家供大家參考,具體如下:
1. 概述
在軟件開發(fā)的過程中,當(dāng)遇到一個(gè)“復(fù)雜的對(duì)象”的創(chuàng)建工作,該對(duì)象由一定各個(gè)部分的子對(duì)象用一定的算法構(gòu)成,由于需求的變化,復(fù)雜對(duì)象的各個(gè)部分經(jīng)常面臨劇烈的變化,但將它們組合在一起的算法相對(duì)穩(wěn)定。
例子1:買肯德基
典型的兒童餐包括一個(gè)主食,一個(gè)輔食,一杯飲料和一個(gè)玩具(例如漢堡、炸雞、可樂和玩具車)。這些在不同的兒童餐中可以是不同的,但是組合成兒童餐的過程是相同的。
客戶端:顧客,想去買一套套餐(這里面包括漢堡,可樂,薯?xiàng)l),可以有1號(hào)和2號(hào)兩種套餐供顧客選擇。
指導(dǎo)者角色:收銀員。知道顧客想要買什么樣的套餐,并告訴餐館員工去準(zhǔn)備套餐。
建造者角色:餐館員工。按照收銀員的要求去準(zhǔn)備具體的套餐,分別放入漢堡,可樂,薯?xiàng)l等。
產(chǎn)品角色:最后的套餐,所有的東西放在同一個(gè)盤子里面。
例子2:計(jì)算工資:工資的計(jì)算一般是:底薪+獎(jiǎng)金-稅。但底薪分為一級(jí)8000、二級(jí)6000、三級(jí)4000三個(gè)等級(jí)。根據(jù)崗位不同獎(jiǎng)金的發(fā)放也不一樣,管理及日常事務(wù)處理崗位(A類)每月根據(jù)領(lǐng)導(dǎo)及同事間的評(píng)議得分計(jì)算獎(jiǎng)金,銷售崗位(B類)則根據(jù)銷售額發(fā)放提成。稅金則根據(jù)獎(jiǎng)金和底薪的數(shù)額進(jìn)行計(jì)算。由此看出該工資的計(jì)算方式是比較穩(wěn)定的構(gòu)建算法,但對(duì)工資的每一部分都會(huì)根據(jù)不同的情況產(chǎn)生不同的算法,如何將客戶端與變化巨烈的底薪、獎(jiǎng)金和稅金計(jì)算方式分離呢,這也比較適合用建造者模式。
2 . 問題
我們?nèi)绾螒?yīng)對(duì)這種變化,如何提供一種“封裝機(jī)制”來(lái)隔離“復(fù)雜對(duì)象的各個(gè)部”的變化,從而保持系統(tǒng)中的“穩(wěn)定構(gòu)建算法”而不隨需求的變化而變化?
3. 解決方案
建造者模式: 將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
4. 適用性
在以下情況使用Builder模式
•當(dāng)創(chuàng)建復(fù)雜對(duì)象的算法應(yīng)該獨(dú)立于該對(duì)象的組成部分以及它們的裝配方式時(shí)。
•當(dāng)構(gòu)造過程必須允許被構(gòu)造的對(duì)象有不同的表示時(shí)。
5. 結(jié) 構(gòu)
此模式結(jié)構(gòu)如下頁(yè)上圖所示。
6. 構(gòu)建模式的組成
• 抽象建造者角色(Builder):為創(chuàng)建一個(gè)Product對(duì)象的各個(gè)部件指定抽象接口,以規(guī)范產(chǎn)品對(duì)象的各個(gè)組成成分的建造。一般而言,此角色規(guī)定要實(shí)現(xiàn)復(fù)雜對(duì)象的哪些部分的創(chuàng)建,并不涉及具體的對(duì)象部件的創(chuàng)建。
• 具體建造者(ConcreteBuilder)
1)實(shí)現(xiàn)Builder的接口以構(gòu)造和裝配該產(chǎn)品的各個(gè)部件。即實(shí)現(xiàn)抽象建造者角色Builder的方法。
2)定義并明確它所創(chuàng)建的表示,即針對(duì)不同的商業(yè)邏輯,具體化復(fù)雜對(duì)象的各部分的創(chuàng)建
3) 提供一個(gè)檢索產(chǎn)品的接口
4) 構(gòu)造一個(gè)使用Builder接口的對(duì)象即在指導(dǎo)者的調(diào)用下創(chuàng)建產(chǎn)品實(shí)例
指導(dǎo)者(Director):調(diào)用具體建造者角色以創(chuàng)建產(chǎn)品對(duì)象的各個(gè)部分。指導(dǎo)者并沒有涉及具體產(chǎn)品類的信息,真正擁有具體產(chǎn)品的信息是具體建造者對(duì)象。它只負(fù)責(zé)保證對(duì)象各部分完整創(chuàng)建或按某種順序創(chuàng)建。
產(chǎn)品角色(Product):建造中的復(fù)雜對(duì)象。它要包含那些定義組件的類,包括將這些組件裝配成產(chǎn)品的接口。
7. 效果
Builder模式的主要效果:
1 ) 它使你可以改變一個(gè)產(chǎn)品的內(nèi)部表示 Builder對(duì)象提供給導(dǎo)向器一個(gè)構(gòu)造產(chǎn)品的抽象接口。該接口使得生成器可以隱藏這個(gè)產(chǎn)品的表示和內(nèi)部結(jié)構(gòu)。它同時(shí)也隱藏了該產(chǎn)品是如何裝配的。因?yàn)楫a(chǎn)品是通過抽象接口構(gòu)造的,你在改變?cè)摦a(chǎn)品的內(nèi)部表示時(shí)所要做的只是定義一個(gè)新的生成器。
2) 它將構(gòu)造代碼和表示代碼分開 Builder模式通過封裝一個(gè)復(fù)雜對(duì)象的創(chuàng)建和表示方式提高了對(duì)象的模塊性??蛻舨恍枰蓝x產(chǎn)品內(nèi)部結(jié)構(gòu)的類的所有信息;這些類是不出現(xiàn)在Builder接口中的。每個(gè)Concrete Builder包含了創(chuàng)建和裝配一個(gè)特定產(chǎn)品的所有代碼。這些代碼只需要寫一次;然后不同的Director可以復(fù)用它以在相同部件集合的基礎(chǔ)上構(gòu)作不同的Product。
3 ) 它使你可對(duì)構(gòu)造過程進(jìn)行更精細(xì)的控制 Builder模式與一下子就生成產(chǎn)品的創(chuàng)建型模式不同,它是在導(dǎo)向者的控制下一步一步構(gòu)造產(chǎn)品的。僅當(dāng)該產(chǎn)品完成時(shí)導(dǎo)向者才從生成器中取回它。因此Builder接口相比其他創(chuàng)建型模式能更好的反映產(chǎn)品的構(gòu)造過程。這使你可以更精細(xì)的控制構(gòu)建過程,從而能更精細(xì)的控制所得產(chǎn)品的內(nèi)部結(jié)構(gòu)。
8. 實(shí)現(xiàn):
指導(dǎo)者:收銀員
<?php /** * 指導(dǎo)者:收銀員 * */ class DirectorCashier { /** * 收銀餐館員工返回的食物 * */ public function buildFood(Builder $builder) { $builder->buildPart1(); $builder->buildPart2(); } }
抽象建造者:
/** * 抽象建造者 * */ abstract class Builder { /** * 創(chuàng)建產(chǎn)品的第一部分 */ public abstract function buildPart1(); /** * * 創(chuàng)建產(chǎn)品的第二部分 */ public abstract function buildPart2(); /** * * 返回產(chǎn)品 */ public abstract function getProduct(); }
具體建造者類:
/** * 具體建造者類:餐館員工,返回的套餐是:漢堡兩個(gè)+飲料一個(gè) * */ class ConcreteBuilder1 extends Builder { protected $_product = null;//產(chǎn)品對(duì)象 function __construct(){ $this->_product = new Product(); } /** * 創(chuàng)建產(chǎn)品的第一部分::漢堡=2 */ public function buildPart1() { $this->_product->add('Hamburger',2); } /** * * 創(chuàng)建產(chǎn)品的第二部分: */ public function buildPart2() { $this->_product->add('Drink', 1); } /** * 返回產(chǎn)品對(duì)象 : * */ public function getProduct() { return $this->_product; } } /** * 具體建造者類:餐館員工,漢堡1個(gè)+飲料2個(gè) * */ class ConcreteBuilder2 extends Builder { protected $_product = null;//產(chǎn)品對(duì)象 function __construct(){ $this->_product = new Product(); } /** * 創(chuàng)建產(chǎn)品的第一部分:漢堡 */ public function buildPart1() { $this->_product->add('Hamburger', 1); } /** * * 創(chuàng)建產(chǎn)品的第二部分:drink=2 */ public function buildPart2() { $this->_product->add('Drink', 2); } /** * 返回產(chǎn)品對(duì)象 : * */ public function getProduct() { return $this->_product; } }
產(chǎn)品類:
/** * 產(chǎn)品類 */ class Product { public $products = array(); /** * 添加具體產(chǎn)品 */ public function add($name, $value) { $this->products[$name] = $value; } /** * 給顧客查看產(chǎn)品 */ public function showToClient() { foreach ($this->products as $key => $v) { echo $key , '=' , $v ,'<br>'; } } }
客戶程序:
//客戶程序 class Client { /** * 顧客購(gòu)買套餐 * */ public function buy($type) { //指導(dǎo)者,收銀員 $director = new DirectorCashier(); //餐館員工,收銀員 $class = new ReflectionClass('ConcreteBuilder' .$type ); $concreteBuilder = $class->newInstanceArgs(); //收銀員組合員工返回的食物 $director->buildFood($concreteBuilder); //返回給顧客 $concreteBuilder->getProduct()->showToClient(); } } //測(cè)試 ini_set('display_errors', 'On'); $c = new Client(); $c->buy(1);//購(gòu)買套餐1 $c->buy(2);//購(gòu)買套餐1
9. 建造者模式的優(yōu)點(diǎn)
首先,建造者模式的封裝性很好。使用建造者模式可以有效的封裝變化,在使用建造者模式的場(chǎng)景中,一般產(chǎn)品類和建造者類是比較穩(wěn)定的,因此,將主要的業(yè)務(wù)邏輯封裝在導(dǎo)演類中對(duì)整體而言可以取得比較好的穩(wěn)定性。
其次,建造者模式很容易進(jìn)行擴(kuò)展。如果有新的需求,通過實(shí)現(xiàn)一個(gè)新的建造者類就可以完成,基本上不用修改之前已經(jīng)測(cè)試通過的代碼,因此也就不會(huì)對(duì)原有功能引入風(fēng)險(xiǎn)。
10. 建造者模式與工廠模式的區(qū)別
我們可以看到,建造者模式與工廠模式是極為相似的,總體上,建造者模式僅僅只比工廠模式多了一個(gè)“導(dǎo)演類”的角色。在建造者模式的類圖中,假如把這個(gè)導(dǎo)演類看做是最終調(diào)用的客戶端,那么圖中剩余的部分就可以看作是一個(gè)簡(jiǎn)單的工廠模式了。
與工廠模式相比,建造者模式一般用來(lái)創(chuàng)建更為復(fù)雜的對(duì)象,因?yàn)閷?duì)象的創(chuàng)建過程更為復(fù)雜,因此將對(duì)象的創(chuàng)建過程獨(dú)立出來(lái)組成一個(gè)新的類——導(dǎo)演類。也就是說,工廠模式是將對(duì)象的全部創(chuàng)建過程封裝在工廠類中,由工廠類向客戶端提供最終的產(chǎn)品;而建造者模式中,建造者類一般只提供產(chǎn)品類中各個(gè)組件的建造,而將具體建造過程交付給導(dǎo)演類。由導(dǎo)演類負(fù)責(zé)將各個(gè)組件按照特定的規(guī)則組建為產(chǎn)品,然后將組建好的產(chǎn)品交付給客戶端。
11. 總結(jié)
建造者模式與工廠模式類似,他們都是建造者模式,適用的場(chǎng)景也很相似。一般來(lái)說,如果產(chǎn)品的建造很復(fù)雜,那么請(qǐng)用工廠模式;如果產(chǎn)品的建造更復(fù)雜,那么請(qǐng)用建造者模式。
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門教程》、《PHP數(shù)組(Array)操作技巧大全》、《PHP基本語(yǔ)法入門教程》、《PHP運(yùn)算與運(yùn)算符用法總結(jié)》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫(kù)操作入門教程》及《php常見數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
- PHP設(shè)計(jì)模式之原型模式示例詳解
- PHP設(shè)計(jì)模式之命令模式示例詳解
- PHP設(shè)計(jì)模式(四)原型模式Prototype實(shí)例詳解【創(chuàng)建型】
- PHP設(shè)計(jì)模式(一)工廠模式Factory實(shí)例詳解【創(chuàng)建型】
- PHP設(shè)計(jì)模式概論【概念、分類、原則等】
- PHP設(shè)計(jì)模式之 策略模式Strategy詳解【對(duì)象行為型】
- PHP設(shè)計(jì)模式入門之狀態(tài)模式原理與實(shí)現(xiàn)方法分析
- PHP設(shè)計(jì)模式入門之迭代器模式原理與實(shí)現(xiàn)方法分析
- PHP設(shè)計(jì)模式之迭代器模式Iterator實(shí)例分析【對(duì)象行為型】
- php設(shè)計(jì)模式之適配器模式實(shí)例分析【星際爭(zhēng)霸游戲案例】
- php設(shè)計(jì)模式之迭代器模式實(shí)例分析【星際爭(zhēng)霸游戲案例】
- 詳解PHP八大設(shè)計(jì)模式
相關(guān)文章
使用gd庫(kù)實(shí)現(xiàn)php服務(wù)端圖片裁剪和生成縮略圖功能分享
一般用戶上傳頭像時(shí),都會(huì)讓用戶自行裁剪圖片。那么php怎么實(shí)現(xiàn)這個(gè)功能呢?php中裁剪圖片主要使用gd庫(kù)的imagecopyresampled方法2013-12-12微信小程序頁(yè)面向下滾動(dòng)時(shí)tab欄固定頁(yè)面頂部實(shí)例講解
這篇文章主要介紹了微信小程序頁(yè)面向下滾動(dòng)時(shí)tab欄固定頁(yè)面頂部實(shí)例講解,文中圖文實(shí)例講解的很透徹,有需要的同學(xué)可以參考下2021-03-03PHP把網(wǎng)頁(yè)保存為word文件的三種方法
最近工作遇到關(guān)于生成word的問題,現(xiàn)在總結(jié)一下生成word的三種方法的相關(guān)資料,需要的朋友可以參考下2014-04-04關(guān)于Yii2框架跑腳本時(shí)內(nèi)存泄漏問題的分析與解決
這篇文章主要給大家介紹了關(guān)于Yii2框架跑腳本時(shí)內(nèi)存泄漏問題的分析與解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Yii2具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12PHP中__set()實(shí)例用法和基礎(chǔ)講解
在本篇文章里小編給大家整理了關(guān)于HP中__set()實(shí)例用法和基礎(chǔ)講解,對(duì)此有需要的朋友們可以學(xué)習(xí)參考下。2019-07-07php 創(chuàng)建以UNIX時(shí)間戳命名的文件夾(示例代碼)
這篇文章主要介紹了php創(chuàng)建以UNIX時(shí)間戳命名的文件夾(示例代碼)。需要的朋友可以過來(lái)參考下,希望對(duì)大家有所幫助2014-03-03