摘要:此模式的主要特點(diǎn)是,與不同,其數(shù)據(jù)模式遵循單一職責(zé)原則。圖代碼你可以在上找到這些代碼代理模式目的為昂貴或者無(wú)法復(fù)制的資源提供接口。圖代碼你可以在上找到這些代碼相關(guān)文章設(shè)計(jì)模式范例創(chuàng)建型設(shè)計(jì)模式
【搬運(yùn)于GitHub開(kāi)源項(xiàng)目DesignPatternsPHP】
項(xiàng)目地址:戳我2、結(jié)構(gòu)型設(shè)計(jì)模式
在軟件工程中,結(jié)構(gòu)型設(shè)計(jì)模式集是用來(lái)抽象真實(shí)程序中的對(duì)象實(shí)體之間的關(guān)系,并使這種關(guān)系可被描述,概括和具體化。
2.1 適配器模式 2.1.1 目的將某個(gè)類(lèi)的接口轉(zhuǎn)換成與另一個(gè)接口兼容。適配器通過(guò)將原始接口進(jìn)行轉(zhuǎn)換,給用戶(hù)提供一個(gè)兼容接口,使得原來(lái)因?yàn)榻涌诓煌鵁o(wú)法一起使用的類(lèi)可以得到兼容。
2.1.2 例子數(shù)據(jù)庫(kù)客戶(hù)端庫(kù)適配器
使用不同的webservices,通過(guò)適配器來(lái)標(biāo)準(zhǔn)化輸出數(shù)據(jù),從而保證不同webservice輸出的數(shù)據(jù)是一致的
2.1.3 UML圖 2.1.4 代碼你可以在 GitHub 上找到這些代碼
BookInterface.php
Book.php
page = 1; } public function turnPage() { $this->page++; } public function getPage(): int { return $this->page; } }EBookAdapter.php
eBook = $eBook; } /** * This class makes the proper translation from one interface to another. */ public function open() { $this->eBook->unlock(); } public function turnPage() { $this->eBook->pressNext(); } /** * notice the adapted behavior here: EBookInterface::getPage() will return two integers, but BookInterface * supports only a current page getter, so we adapt the behavior here * * @return int */ public function getPage(): int { return $this->eBook->getPage()[0]; } }EBookInterface.php
Kindle.php
page++; } public function unlock() { } /** * returns current page and total number of pages, like [10, 100] is page 10 of 100 * * @return int[] */ public function getPage(): array { return [$this->page, $this->totalPages]; } }2.2 橋接模式 2.2.1 目的解耦一個(gè)對(duì)象的實(shí)現(xiàn)與抽象,這樣兩者可以獨(dú)立地變化。
2.2.2 例子Symfony DoctrineBridge
2.2.3 UML圖 2.2.4 代碼你可以在 GitHub 上找到這些代碼
Formatter.php
PlainTextFormatter.php
HtmlFormatter.php
%s", $text); } }Service.php
implementation = $printer; } /** * @param Formatter $printer */ public function setImplementation(Formatter $printer) { $this->implementation = $printer; } abstract public function get(): string; }HelloWorldService.php
implementation->format("Hello World"); } }PingService.php
implementation->format("pong"); } }2.3 組合模式 2.3.1 目的以單個(gè)對(duì)象的方式來(lái)對(duì)待一組對(duì)象
2.3.2 例子form類(lèi)的實(shí)例包含多個(gè)子元素,而它也像單個(gè)子元素那樣響應(yīng)render()請(qǐng)求,當(dāng)調(diào)用render()方法時(shí),它會(huì)歷遍所有的子元素,調(diào)用render()方法
Zend_Config: 配置選項(xiàng)樹(shù), 其每一個(gè)分支都是Zend_Config對(duì)象
2.3.3 UML圖 2.3.4 代碼你可以在 GitHub 上找到這些代碼
RenderableInterface.php
Form.php
"; foreach ($this->elements as $element) { $formCode .= $element->render(); } $formCode .= ""; return $formCode; } /** * @param RenderableInterface $element */ public function addElement(RenderableInterface $element) { $this->elements[] = $element; } }InputElement.php
"; } }TextElement.php
text = $text; } public function render(): string { return $this->text; } }2.4 數(shù)據(jù)映射器 2.4.1 目的數(shù)據(jù)映射器是一個(gè)數(shù)據(jù)訪問(wèn)層,用于將數(shù)據(jù)在持久性數(shù)據(jù)存儲(chǔ)(通常是一個(gè)關(guān)系數(shù)據(jù)庫(kù))和內(nèi)存中的數(shù)據(jù)表示(領(lǐng)域?qū)樱┲g進(jìn)行相互轉(zhuǎn)換。其目的是為了將數(shù)據(jù)的內(nèi)存表示、持久存儲(chǔ)、數(shù)據(jù)訪問(wèn)進(jìn)行分離。該層由一個(gè)或者多個(gè)映射器組成(或者數(shù)據(jù)訪問(wèn)對(duì)象),并且進(jìn)行數(shù)據(jù)的轉(zhuǎn)換。映射器的實(shí)現(xiàn)在范圍上有所不同。通用映射器將處理許多不同領(lǐng)域的實(shí)體類(lèi)型,而專(zhuān)用映射器將處理一個(gè)或幾個(gè)。
此模式的主要特點(diǎn)是,與Active Record不同,其數(shù)據(jù)模式遵循單一職責(zé)原則(Single Responsibility Principle)。
2.4.2 例子DB對(duì)象關(guān)系映射器(ORM): Doctrine2使用“EntityRepository”作為DAO
2.4.3 UML圖 2.4.4 代碼你可以在 GitHub 上找到這些代碼
User.php
username = $username; $this->email = $email; } /** * @return string */ public function getUsername() { return $this->username; } /** * @return string */ public function getEmail() { return $this->email; } }UserMapper.php
adapter = $storage; } /** * finds a user from storage based on ID and returns a User object located * in memory. Normally this kind of logic will be implemented using the Repository pattern. * However the important part is in mapRowToUser() below, that will create a business object from the * data fetched from storage * * @param int $id * * @return User */ public function findById(int $id): User { $result = $this->adapter->find($id); if ($result === null) { throw new InvalidArgumentException("User #$id not found"); } return $this->mapRowToUser($result); } private function mapRowToUser(array $row): User { return User::fromState($row); } }StorageAdapter.php
data = $data; } /** * @param int $id * * @return array|null */ public function find(int $id) { if (isset($this->data[$id])) { return $this->data[$id]; } return null; } }2.5 裝飾器 2.5.1 目的動(dòng)態(tài)地為類(lèi)的實(shí)例添加功能
2.5.2 例子Zend Framework: Zend_Form_Element 實(shí)例的裝飾器
Web Service層:REST服務(wù)的JSON與XML裝飾器(當(dāng)然,在此只能使用其中的一種)
2.5.3 UML圖 2.5.4 代碼你可以在 GitHub 上找到這些代碼
Booking.php
BookingDecorator.php
booking = $booking; } }DoubleRoomBooking.php
ExtraBed.php
booking->calculatePrice() + self::PRICE; } public function getDescription(): string { return $this->booking->getDescription() . " with extra bed"; } }WiFi.php
booking->calculatePrice() + self::PRICE; } public function getDescription(): string { return $this->booking->getDescription() . " with wifi"; } }2.6 依賴(lài)注入 2.6.1 目的實(shí)現(xiàn)了松耦合的軟件架構(gòu),可得到更好的測(cè)試,管理和擴(kuò)展的代碼
2.6.2 用例注入DatabaseConfiguration, DatabaseConnection將從$config獲得所需的所有內(nèi)容。沒(méi)有DI(依賴(lài)注入),配置將直接在DatabaseConnection中創(chuàng)建,這不利于測(cè)試和擴(kuò)展它。
2.6.3 例子Doctrine2 ORM 使用了依賴(lài)注入,它通過(guò)配置注入了 Connection 對(duì)象。為了達(dá)到方便測(cè)試的目的,可以很容易的通過(guò)配置創(chuàng)建一個(gè)mock的 Connection 對(duì)象。
Symfony 和 Zend Framework 2 也有了專(zhuān)門(mén)的依賴(lài)注入容器,用來(lái)通過(guò)配置數(shù)據(jù)創(chuàng)建需要的對(duì)象(比如在控制器中使用依賴(lài)注入容器獲取所需的對(duì)象)
2.6.4 UML圖 2.6.5 代碼你可以在 GitHub 上找到這些代碼
DatabaseConfiguration.php
host = $host; $this->port = $port; $this->username = $username; $this->password = $password; } public function getHost(): string { return $this->host; } public function getPort(): int { return $this->port; } public function getUsername(): string { return $this->username; } public function getPassword(): string { return $this->password; } }DatabaseConnection.php
configuration = $config; } public function getDsn(): string { // this is just for the sake of demonstration, not a real DSN // notice that only the injected config is used here, so there is // a real separation of concerns here return sprintf( "%s:%s@%s:%d", $this->configuration->getUsername(), $this->configuration->getPassword(), $this->configuration->getHost(), $this->configuration->getPort() ); } }2.7 外觀模式 2.7.1 目的Facade模式的主要目標(biāo)不是避免您必須閱讀復(fù)雜API的手冊(cè)。這只是副作用。主要目的是減少耦合并遵循Demeter定律。
Facade通過(guò)嵌入多個(gè)(當(dāng)然,有時(shí)只有一個(gè))接口來(lái)解耦訪客與子系統(tǒng),當(dāng)然也降低復(fù)雜度。
Facade不會(huì)禁止你訪問(wèn)子系統(tǒng)
你可以為一個(gè)子系統(tǒng)提供多個(gè) Facade
因此一個(gè)好的 Facade 里面不會(huì)有 new 。如果每個(gè)方法里都要構(gòu)造多個(gè)對(duì)象,那么它就不是 Facade,而是生成器或者 [ 抽象 | 靜態(tài) | 簡(jiǎn)單 ] 工廠方法。優(yōu)秀的 Facade 不會(huì)有 new,并且構(gòu)造函數(shù)參數(shù)是接口類(lèi)型的。如果你需要?jiǎng)?chuàng)建一個(gè)新實(shí)例,則在參數(shù)中傳入一個(gè)工廠對(duì)象。
2.7.2 UML圖 2.7.3 代碼你可以在 GitHub 上找到這些代碼
Facade.php
bios = $bios; $this->os = $os; } public function turnOn() { $this->bios->execute(); $this->bios->waitForKeyPress(); $this->bios->launch($this->os); } public function turnOff() { $this->os->halt(); $this->bios->powerDown(); } }OsInterface.php
BiosInterface.php
2.8 連貫接口 2.8.1 目的用來(lái)編寫(xiě)易于閱讀的代碼,就像自然語(yǔ)言一樣(如英語(yǔ))
2.8.2 例子Doctrine2 的 QueryBuilder,就像下面例子中類(lèi)似
PHPUnit 使用連貫接口來(lái)創(chuàng)建 mock 對(duì)象
Yii 框架:CDbCommand 與 CActiveRecord 也使用此模式
2.8.3 UML圖 2.8.4 代碼你可以在 GitHub 上找到這些代碼
Sql.php
fields = $fields; return $this; } public function from(string $table, string $alias): Sql { $this->from[] = $table." AS ".$alias; return $this; } public function where(string $condition): Sql { $this->where[] = $condition; return $this; } public function __toString(): string { return sprintf( "SELECT %s FROM %s WHERE %s", join(", ", $this->fields), join(", ", $this->from), join(" AND ", $this->where) ); } }2.9 享元 2.9.1 目的為了盡可能減少內(nèi)存使用,Flyweight與類(lèi)似的對(duì)象共享盡可能多的內(nèi)存。當(dāng)使用大量狀態(tài)相差不大的對(duì)象時(shí),就需要它。通常的做法是保持外部數(shù)據(jù)結(jié)構(gòu)中的狀態(tài),并在需要時(shí)將其傳遞給flyweight對(duì)象。
2.9.2 UML圖 2.9.3 代碼你可以在 GitHub 上找到這些代碼
FlyweightInterface.php
CharacterFlyweight.php
name = $name; } public function render(string $font): string { // Clients supply the context-dependent information that the flyweight needs to draw itself // For flyweights representing characters, extrinsic state usually contains e.g. the font. return sprintf("Character %s with font %s", $this->name, $font); } }FlyweightFactory.php
pool[$name])) { $this->pool[$name] = new CharacterFlyweight($name); } return $this->pool[$name]; } public function count(): int { return count($this->pool); } }2.10 代理模式 2.10.1 目的為昂貴或者無(wú)法復(fù)制的資源提供接口。
2.10.2 例子Doctrine2 使用代理來(lái)實(shí)現(xiàn)框架特性(如延遲初始化),同時(shí)用戶(hù)還是使用自己的實(shí)體類(lèi)并且不會(huì)使用或者接觸到代理
2.10.3 UML圖 2.10.4 代碼你可以在 GitHub 上找到這些代碼
BankAccount.php
HeavyBankAccount.php
transactions[] = $amount; } public function getBalance(): int { // this is the heavy part, imagine all the transactions even from // years and decades ago must be fetched from a database or web service // and the balance must be calculated from it return array_sum($this->transactions); } }BankAccountProxy.php
balance === null) { $this->balance = parent::getBalance(); } return $this->balance; } }2.11 注冊(cè)模式 2.11.1 目的要為整個(gè)應(yīng)用程序中經(jīng)常使用的對(duì)象實(shí)現(xiàn)中央存儲(chǔ),通常只使用靜態(tài)方法(或使用單例模式)的抽象類(lèi)來(lái)實(shí)現(xiàn)。請(qǐng)記住,這將引入全局狀態(tài),這在任何時(shí)候都應(yīng)該避免!而是使用依賴(lài)注入來(lái)實(shí)現(xiàn)它!
2.11.2 例子Zend Framework 1: Zend_Registry 持有應(yīng)用的logger對(duì)象,前端控制器等。
Yii 框架: CWebApplication 持有所有的應(yīng)用組件,如 CWebUser, CUrlManager, 等。
2.11.3 UML圖 2.11.4 代碼你可以在 GitHub 上找到這些代碼
Registry.php
相關(guān)文章:
PHP設(shè)計(jì)模式范例 — DesignPatternsPHP(1)創(chuàng)建型設(shè)計(jì)模式
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/29982.html
摘要:抽象工廠目的創(chuàng)建一系列相關(guān)或依賴(lài)的對(duì)象,而不指定它們的具體類(lèi)。這個(gè)模式是一個(gè)真正的設(shè)計(jì)模式,因?yàn)樗裱艘蕾?lài)反轉(zhuǎn)原則眾所周知這個(gè)代表了真正的面向?qū)ο蟪绦蛟O(shè)計(jì)。 【搬運(yùn)于GitHub開(kāi)源項(xiàng)目DesignPatternsPHP】 項(xiàng)目地址:戳我 1、創(chuàng)建型設(shè)計(jì)模式 在軟件工程中,創(chuàng)建型設(shè)計(jì)模式承擔(dān)著對(duì)象創(chuàng)建的職責(zé),嘗試創(chuàng)建適合程序上下文的對(duì)象,對(duì)象創(chuàng)建設(shè)計(jì)模式的產(chǎn)生是由于軟件工程設(shè)計(jì)的問(wèn)...
摘要:圖示代碼示例服務(wù)實(shí)例索引服務(wù)定義索引是否全局服務(wù)共享單例模式實(shí)例化省略服務(wù)實(shí)例化實(shí)現(xiàn)無(wú)法定位服務(wù)服務(wù)添加失敗感謝文中圖片來(lái)源來(lái)源網(wǎng)絡(luò) 什么是服務(wù)定位器 服務(wù)定位器(service locator)他知道如何定位(創(chuàng)建或者獲取)一個(gè)應(yīng)用所需要的服務(wù),服務(wù)使用者在實(shí)際使用中無(wú)需關(guān)心服務(wù)的實(shí)際實(shí)現(xiàn)。 有什么作用 實(shí)現(xiàn)服務(wù)使用者和服務(wù)的解耦,無(wú)需改變代碼而只是通過(guò)簡(jiǎn)單配置更服服務(wù)實(shí)現(xiàn)。 UML...
摘要:面向?qū)ο笤O(shè)計(jì)模式通常以類(lèi)別或?qū)ο髞?lái)描述其中的關(guān)系和相互作用,但不涉及用來(lái)完成應(yīng)用程序的特定類(lèi)別或?qū)ο蟆@锸洗鷵Q原則里氏代換原則是面向?qū)ο笤O(shè)計(jì)的基本原則之一。 通俗易懂的設(shè)計(jì)模式 零、使用 1、安裝 2、測(cè)試 一、什么是設(shè)計(jì)模式 二、設(shè)計(jì)模式的類(lèi)型 三、設(shè)計(jì)模式的六大原則 四、UML類(lèi)圖 1、看懂UML類(lèi)圖 2、解釋 五、資料 前言:花了一些時(shí)間再次熟悉了一遍...
摘要:帶有兩個(gè)特殊的變量,專(zhuān)門(mén)用來(lái)達(dá)到這個(gè)目的一個(gè)是變量,它通過(guò)命令行把傳遞給腳本的參數(shù)保存為單獨(dú)的數(shù)組元素另一個(gè)是變量,它用來(lái)保存數(shù)組里元素的個(gè)數(shù)。 本文為轉(zhuǎn)載,原文鏈接: 參考文章 所有的PHP發(fā)行版,不論是編譯自源代碼的版本還是預(yù)創(chuàng)建的版本,都在默認(rèn)情況下帶有一個(gè)PHP可執(zhí)行文件。這個(gè)可執(zhí)行文件可以被用來(lái)運(yùn)行命令行的PHP程序。要在你的系統(tǒng)上找到這個(gè)可執(zhí)行文件,就要遵照下面的步驟: 1...
前言 在若干次前的一場(chǎng)面試,面試官看我做過(guò)python爬蟲(chóng)/后端 的工作,順帶問(wèn)了我些后端相關(guān)的問(wèn)題:你覺(jué)得什么是后端? 送命題。當(dāng)時(shí)腦瓦特了,答曰:邏輯處理和數(shù)據(jù)增刪改查。。。 showImg(https://user-gold-cdn.xitu.io/2019/4/24/16a4ed4fc8c18078); 當(dāng)場(chǎng)被懟得體無(wú)完膚,羞愧難當(dāng)。事后再反思這問(wèn)題,結(jié)合資料總結(jié)了一下。發(fā)現(xiàn)自己學(xué)過(guò)的Re...
閱讀 2080·2021-09-29 09:35
閱讀 686·2021-09-08 09:36
閱讀 3393·2021-09-03 10:30
閱讀 2111·2019-08-30 14:21
閱讀 2911·2019-08-30 11:18
閱讀 3311·2019-08-29 17:31
閱讀 3141·2019-08-29 17:29
閱讀 1309·2019-08-29 17:13