摘要:原文地址設(shè)計模式六世紀(jì)年代,計算機發(fā)展迅速,編程技術(shù)也日益分化。到了年代,的出現(xiàn)更是讓這種程序設(shè)計模式得以延續(xù)。根據(jù)設(shè)計模式三封裝中介紹的設(shè)計原則,在面向?qū)ο蟪绦蛟O(shè)計中,類和類之間的訪問交互和更新應(yīng)該是通過和。
Introduction原文地址:PHP設(shè)計模式(六):MVC
20世紀(jì)80年代,計算機發(fā)展迅速,編程技術(shù)也日益分化。桌面應(yīng)用編程,也逐漸出現(xiàn)了用戶圖形界面和程序邏輯分離的程序設(shè)計。到了90年代,web的出現(xiàn)更是讓這種程序設(shè)計模式得以延續(xù)。
這種設(shè)計模式便是MVC(Model-View-Control),除了MVC,還有MVC的變種,如MVVM(Model-View-View Model)等。
回到80年代的桌面應(yīng)用編程,當(dāng)時面向?qū)ο蟮木幊淘O(shè)計模式(見PHP設(shè)計模式(一):基礎(chǔ)編程模式)興起,程序員將桌面應(yīng)用分割成兩個大的對象:領(lǐng)域?qū)ο?domain objects)和可視對象(presentation objects)。領(lǐng)域?qū)ο笫菍ΜF(xiàn)實事物的抽象模型,可視對象是對用戶界面部分的抽象模型。
后來人們發(fā)現(xiàn),只有領(lǐng)域?qū)ο蠛涂梢晫ο笫遣粔虻?,特別是在復(fù)雜的業(yè)務(wù)中。根據(jù)PHP設(shè)計模式(三):封裝中介紹的設(shè)計原則,在面向?qū)ο蟪绦蛟O(shè)計中,類和類之間的訪問、交互和更新應(yīng)該是通過Accessors和Mutators。
那么如果操作領(lǐng)域?qū)ο竽??人們引入了控制?controller)的對象,通過控制器來操作領(lǐng)域模型。
到此,MVC模型逐漸穩(wěn)定下來,用戶通過可視對象操作控制器對象,控制器對象再去操作領(lǐng)域?qū)ο蟆?/p>
MVC中的設(shè)計模式
上面介紹的MVC屬于抽象度比較高的設(shè)計模式,在實際編程中,需要遵守下面的設(shè)計模式。
基于接口去編程基于接口去編程的好處就是分離設(shè)計和實現(xiàn),這一點我們在PHP設(shè)計模式(二):抽象類和接口已經(jīng)介紹過了,下面我們舉一個實際的例子來說明這個設(shè)計的好處。
eatFish()) { echo $this->name . " can eat fish. "; } if ($this->eatMoss()) { echo $this->name . " can eat moss. "; } } } ?>
我們創(chuàng)建一個鯨魚類:
name = "Whale"; } public function eatFish() { return TRUE; } public function eatMoss() { return FALSE; } } $whale = new Whale(); $whale->eat(); ?>
運行一下:
$ php Whale.php Whale eats fish.
看上去沒什么問題,對吧?我們創(chuàng)建一個鯉魚類:
name = "Carp"; } public function eatMoss() { return TRUE; } } $carp = new Carp(); $carp->eat(); ?>
運行一下:
$ php Carp.php PHP Fatal error: Class Carp contains 1 abstract method and must therefore be declared abstract or implement the remaining method (Animal::eatFish) in Carp.php on line 9
報錯了,對吧?因為我們實現(xiàn)Carp.php的時候故意沒有去實現(xiàn)eatFish接口,基于接口的編程設(shè)計模式可以在開發(fā)期就發(fā)現(xiàn)這種邏輯錯誤。
使用組件而不是繼承將一個對象拆成更小的對象,這些小的對象成為組件(composition)。盡量使用組件而不是繼承的設(shè)計模式的意義在于,多種繼承之下,子類可能會擁有大量毫無意義的未實現(xiàn)方法。而通過組件的方式,子類可以選擇需要的組件。
下面給出一個例子:
eatFish()) { echo $this->name . " can eat fish. "; } if ($this->eatMoss()) { echo $this->name . " can eat moss. "; } } } class Whale extends Animal { protected function __construct() { $this->name = "Whale"; } protected function eatFish() { return TRUE; } protected function eatMoss() { return FALSE; } } class BullWhale extends Whale { public function __construct() { $this->name = "Bull Whale"; } public function getGender() { return "Male"; } } ?>
這里的BullWhale其實非常冗余,實際的業(yè)務(wù)模型可能并不需要這么復(fù)雜,這就是多重繼承的惡果。
而組件則不同,通過將行為拆分成不同的部分,又最終子類決定使用哪些組件。
下面給出一個例子:
name = $name; } public function eat($food) { echo $this->name . " eat ". $food . ". "; } } class Gender { private $gender; public function __construct($gender) { $this->gender= $gender; } public function getGender() { return $this->gender; } } class BullWhale { private $action; private $gender; public function __construct() { $this->action = new Action("Bull Whale"); $this->gender = new Gender("Male"); } public function eatFood($food) { $this->action->eat($food); } public function getGender() { return $this->gender->getGender(); } } $bullWhale = new BullWhale(); $bullWhale->eatFood("fish"); echo $bullWhale->getGender() . " "; ?>
運行一下:
$ php BullWhale.php Bill Whale eat fish. Male
BullWhale由Action和Gender組件構(gòu)成,不同的類可以選擇不同的組件組合,這樣就不會造成類冗余了。
Summary實際編程中,更多的往往是混合架構(gòu),如既包含繼承,又包含組件的編程設(shè)計模式。不過,掌握基本的編程架構(gòu)設(shè)計是一切的基礎(chǔ)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/21619.html
摘要:學(xué)習(xí)路線圖建議最后買一個域名和阿里云服務(wù)器,真正的將代碼部署到云服務(wù)器上去,走一次上線流程,用一下管理一下代碼會更棒。建議學(xué)習(xí)路線圖這個時候使用寫一個大并發(fā)的多服務(wù)器的秒殺出來。 PHP學(xué)習(xí)路線圖 在網(wǎng)上很多人公布了太多的PHP學(xué)習(xí)路線圖,本人在互聯(lián)網(wǎng)公司工作十余年,也帶了很多PHP入門的新手,將他們的一些問題和學(xué)習(xí)路線圖為大家整理出來,希望很多小白少走彎路。 一、 網(wǎng)上某些錯誤的學(xué)習(xí)...
摘要:面向?qū)ο笕筇卣骼^承性多態(tài)性封裝性接口。第五階段封裝一個屬于自己的框架框架封裝基礎(chǔ)事件流冒泡捕獲事件對象事件框架選擇框架。核心模塊和對象全局對象,,,事件驅(qū)動,事件發(fā)射器加密解密,路徑操作,序列化和反序列化文件流操作服務(wù)端與客戶端。 第一階段: HTML+CSS:HTML進階、CSS進階、div+css布局、HTML+css整站開發(fā)、 JavaScript基礎(chǔ):Js基礎(chǔ)教程、js內(nèi)置對...
摘要:面向?qū)ο笕筇卣骼^承性多態(tài)性封裝性接口。第五階段封裝一個屬于自己的框架框架封裝基礎(chǔ)事件流冒泡捕獲事件對象事件框架選擇框架。核心模塊和對象全局對象,,,事件驅(qū)動,事件發(fā)射器加密解密,路徑操作,序列化和反序列化文件流操作服務(wù)端與客戶端。 第一階段: HTML+CSS:HTML進階、CSS進階、div+css布局、HTML+css整站開發(fā)、 JavaScript基礎(chǔ):Js基礎(chǔ)教程、js內(nèi)置對...
摘要:在前面的文章中實現(xiàn)的功能時,目標(biāo)類都只能被一個切面代理,如果想要生成第二個代理類,就會把之前的代理類覆蓋。改裝原有功能現(xiàn)在要改裝原來的的實現(xiàn)代碼,讓的功能加入到框架中為了讓切面能夠排序,先添加一個注解,用于標(biāo)記排序。 前言 在前面從零開始實現(xiàn)一個簡易的Java MVC框架(四)--實現(xiàn)AOP和從零開始實現(xiàn)一個簡易的Java MVC框架(五)--引入aspectj實現(xiàn)AOP切點這兩節(jié)文章...
閱讀 841·2021-09-22 15:18
閱讀 1196·2021-09-09 09:33
閱讀 2766·2019-08-30 10:56
閱讀 1203·2019-08-29 16:30
閱讀 1499·2019-08-29 13:02
閱讀 1471·2019-08-26 13:55
閱讀 1653·2019-08-26 13:41
閱讀 1950·2019-08-26 11:56