您好,登錄后才能下訂單哦!
這篇文章主要介紹“PHP中常見的開發模式有哪些及怎么實現”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“PHP中常見的開發模式有哪些及怎么實現”文章能幫助大家解決問題。
設計模式六大原則
開放封閉原則:一個軟件實體如類、模塊和函數應該對擴展開放,對修改關閉。
里氏替換原則:所有引用基類的地方必須能透明地使用其子類的對象.
依賴倒置原則:高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。
單一職責原則:不要存在多于一個導致類變更的原因。通俗的說,即一個類只負責一項職責。
接口隔離原則:客戶端不應該依賴它不需要的接口;一個類對另一個類的依賴應該建立在最小的接口上。
迪米特法則:一個對象應該對其他對象保持最少的了解。
特點: 使用單例模式, 則可以避免大量的new 操作消耗的資源
單例類不能直接實例化創建,而是只能由類本身實例化。因此,要獲得這樣的限制效果,構造函數必須標記為private,從而防止類被實例化。
需要一個私有靜態成員變量來保存類實例和公開一個能訪問到實例的公開靜態方法。
在PHP中,為了防止他人對單例類實例克隆,通常還為其提供一個空的私有__clone()方法。
$_instance必須聲明為靜態的私有變量
構造函數和析構函數必須聲明為私有,防止外部程序new 類從而失去單例模式的意義
getInstance()方法必須設置為公有的,必須調用此方法 以返回實例的一個引用
::操作符只能訪問靜態變量和靜態函數
new對象都會消耗內存
使用場景:最常用的地方是數據庫連接。
使用單例模式生成一個對象后, 該對象可以被其它眾多對象所使用。
私有的__clone()方法防止克隆對象
<?php
class Singleton{
//私有屬性,用于保存實例
private static $instance;
//構造方法私有化,防止外部創建實例
private function __construct(){}//公有方法,用于獲取實例
public static function getInstance(){
//判斷實例有無創建,沒有的話創建實例并返回,有的話直接返回
if(!(self::$instance instanceof self)){
self::$instance = new self();
}
return self::$instance;
}
//克隆方法私有化,防止復制實例
private function __clone(){}}
工廠模式,工廠方法或者類生成對象,而不是在代碼中直接new。
使用方法 new實例化類,每次實例化只需調用工廠類中的方法實例化即可。
優點:由于一個類可能會在很多地方被實例化。當類名或參數發生變化時,工廠模式可簡單快捷的在工廠類下的方法中一次性修改,避免了一個個的去修改實例化的對象
Test1.php
<?php
class Test1
{
static function test()
{
echo FILE;
}
}Factory.php
<?php
class Factory
{
/**
*如果某個類在很多的文件中都new ClassName(),那么萬一這個類的名字
*發生變更或者參數發生變化,如果不使用工廠模式,就需要修改每一個PHP
*代碼,使用了工廠模式之后,只需要修改工廠類或者方法就可以了。
*/
static function createDatabase()
{
$test = new Test1();
return $test;
}
}
Test.php
<?php
spl_autoload_register('autoload1');
$test = Factory::createDatabase();
$test->test();function autoload1($class)
{
$dir = __DIR__;
$requireFile = $dir."\".$class.".php";
require $requireFile;
}}
Test1.php
<?php
class Test1
{
protected static tt)
{
echo "對象已經創建<br>";
return self::tt = new Test1();
echo "創建對象<br>";
return self::$tt;
}
}function echoHello()
{
echo "Hello<br>";
}}
Test.php
<?php
spl_autoload_register('autoload1');
$test = Test1::getInstance();
$test->echoHello();
$test = Test1::getInstance();
$test->echoHello();
$test = Test1::getInstance();
$test->echoHello();
$test = Test1::getInstance();
$test->echoHello();function autoload1($class)
{
$dir = __DIR__;
$requireFile = $dir."\".$class.".php";
require $requireFile;
}}
舉個例子,假設矩形、圓都有同樣的一個方法,那么我們用基類提供的API來創建實例時,通過傳參數來自動創建對應的類的實例,他們都有獲取周長和面積的功能
<?php
interface InterfaceShape
{
function getArea();
function getCircumference();
}/**
? 矩形
*/
class Rectangle implements InterfaceShape
{
private $width;
private $height;
public function __construct($width, $height)
{
$this->width = $width;
$this->height = $height;
}
public function getArea()
{
return $this->width* $this->height;
}
public function getCircumference()
{
return 2 * $this->width + 2 * $this->height;
}
}/**
? 圓形
*/
class Circle implements InterfaceShape
{
private $radius;
function __construct($radius)
{
$this->radius = $radius;
}
public function getArea()
{
return M_PI * pow($this->radius, 2);
}
public function getCircumference()
{
return 2 * M_PI * $this->radius;
}
}/**
? 形狀工廠類
*/
class FactoryShape
{
public static function create()
{
switch (func_num_args()) {
case1:
return newCircle(func_get_arg(0));
case2:
return newRectangle(func_get_arg(0), func_get_arg(1));
default:
# code...
break;
}
}
}rect);
echo "<br>";// object(Circle)#2 (1) { ["radius":"Circle":private]=> int(4) }
circle);
注冊模式,解決全局共享和交換對象。已經創建好的對象,掛在到某個全局可以使用的數組上,在需要使用的時候,直接從該數組上獲取即可。將對象注冊到全局的樹上。任何地方直接去訪問。
<?php
class Register
{
protected static $objects;//將對象注冊到全局的樹上
function set($alias,$object)
{
self::$objects[$alias] = $object;//將對象放到樹上
}
static function get($name)
{
return self::$objects[$name];//獲取某個注冊到樹上的對象
}
function _unset($alias)
{
unset(self::$objects[$alias]);//移除某個注冊到樹上的對象。
}}
策略模式,將一組特定的行為和算法封裝成類,以適應某些特定的上下文環境。
eg:假如有一個電商網站系統,針對男性女性用戶要各自跳轉到不同的商品類目,并且所有的廣告位展示不同的廣告。在傳統的代碼中,都是在系統中加入各種if else的判斷,硬編碼的方式。如果有一天增加了一種用戶,就需要改寫代碼。使用策略模式,如果新增加一種用戶類型,只需要增加一種策略就可以。其他所有的地方只需要使用不同的策略就可以。
首先聲明策略的接口文件,約定了策略的包含的行為。然后,定義各個具體的策略實現類。
UserStrategy.php
<?php
/*? 聲明策略文件的接口,約定策略包含的行為
*/interface UserStrategy {
function showAd();
function showCategory();
}FemaleUser.php
<?phprequire_once 'Loader.php';
class FemaleUser implements UserStrategy {
function showAd() {
echo "2016冬季女裝";
}function showCategory(){
echo "女裝";
}}
MaleUser.php
<?phprequire_once 'Loader.php';
class MaleUser implements UserStrategy {
function showAd(){
echo "IPhone6s";
}function showCategory(){
echo "電子產品";
}}
Page.php//執行文件
<?php
require_once 'Loader.php';
class Page {
protected $strategy;function index(){
echo "AD";
$this->strategy->showAd();
echo "<br>";
echo "Category";
$this->strategy->showCategory();
echo "<br>";
}
function setStrategy(UserStrategy $strategy){
$this->strategy = $strategy;
}}
$page = new Page();
if(isset($_GET['male'])){
$strategy = new MaleUser();
}else {
$strategy = new FemaleUser();
}strategy);
$page->index();
總結:
通過以上方式,可以發現,在不同用戶登錄時顯示不同的內容,但是解決了在顯示時的硬編碼的問題。如果要增加一種策略,只需要增加一種策略實現類,然后在入口文件中執行判斷,傳入這個類即可。實現了解耦。 實現依賴倒置和控制反轉 (有待理解); 通過接口的方式,使得類和類之間不直接依賴。在使用該類的時候,才動態的傳入該接口的一個實現類。如果要替換某個類,只需要提供一個實現了該接口的實現類,通過修改一行代碼即可完成替換。
觀察者模式(Observer),當一個對象狀態發生變化時,依賴它的對象全部會收到通知,并自動更新(一個對象通過提供方法允許另一個對象即觀察者 注冊自己)使本身變得可觀察。當可觀察的對象更改時,它會將消息發送到已注冊的觀察者)
場景1:一個事件發生后,要執行一連串更新操作。傳統的編程方式,就是在事件的代碼之后直接加入處理的邏輯。當更新的邏輯增多之后,代碼會變得難以維護。這種方式是耦合的,侵入式的,增加新的邏輯需要修改事件的主體代碼。
場景2: 用戶登錄,需要寫日志,送積分,參與活動等;使用消息隊列,把用戶和日志,積分,活動之間解耦合
觀察者模式實現了低耦合,非侵入式的通知與更新機制。
<?php
/*
觀察者接口
*/
interface InterfaceObserver
{
function onListen($sender, $args);
function getObserverName();
}// 可被觀察者接口
interface InterfaceObservable
{
function addObserver(observer_name);
}// 觀察者抽象類
abstract class Observer implements InterfaceObserver
{
protected $observer_name;function getObserverName()
{
return $this->observer_name;
}function onListen($sender, $args)
{}
}// 可被觀察類
abstract class Observable implements InterfaceObservable
{
protected $observers = array();public function addObserver(observerinstanceofInterfaceObserver)
{
$this->observers[] = $observer;
}
}public function removeObserver(this->observersas $index => observer->getObserverName() === this->observers, $index, 1);
return;
}
}
}
}// 模擬一個可以被觀察的類
class A extends Observable
{
public function addListener(this->observersas $observer)
{
this, $listener);
}
}
}// 模擬一個觀察者類
class B extends Observer
{
protected $observer_name = 'B';public function onListen($sender, sender);
echo "<br>";
var_dump($args);
echo "<br>";
}
}// 模擬另外一個觀察者類
class C extends Observer
{
protected $observer_name = 'C';public function onListen($sender, sender);
echo "<br>";
var_dump($args);
echo "<br>";
}
}a->addObserver(new B());
$a->addObserver(new C());// 可以看到觀察到的信息
$a->addListener('D');// 移除觀察者
$a->removeObserver('B');// 打印的信息:
// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
// string(1) "D"
// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
// string(1) "D"
裝飾器模式, 根據運行時不同的情景動態地為某個對象調用前后添加不同的行
一個類提供了一項功能,如果要在修改并添加額外的功能,傳統的編程模式,需要寫一個子類繼承它,并重寫實現類的方法,使用裝飾器模式,僅需要在運行時添加一個裝飾器對象即可實現,可以實現最大額靈活性
場景:
1.symfony 控制器中beforepost afterpost 中post提交前和提交后,對數據處理
2.當某一功能或方法draw,要滿足不同的功能需求時,可以使用裝飾器模式
/**
? 輸出一個字符串
? 裝飾器動態添加功能
? Class EchoText
*/
class EchoText
{
protected $decorator = [];
public function Index()
{
//調用裝飾器前置操作
$this->beforeEcho();
echo "你好,我是裝飾器。";
//調用裝飾器后置操作
$this->afterEcho();
}
//增加裝飾器
public function addDecorator(Decorator $decorator)
{
$this->decorator[] = $decorator;
}
//執行裝飾器前置操作 先進先出原則
protected function beforeEcho()
{
foreach ($this->decorator as $decorator)
$decorator->before();
}
//執行裝飾器后置操作 先進后出原則
protected function afterEcho()
{
this->decorator);
foreach ($tmp as $decorator)
$decorator->after();
}
}/**
? 裝飾器接口
? Class Decorator
*/
interface Decorator
{
public function before();
public function after();
}/**
? 顏色裝飾器實現
? Class ColorDecorator
*/
class ColorDecorator implements Decorator
{
protected $color;
public function __construct($color)
{
$this->color = $color;
}
public function before()
{
echo "<dis style='color: {$this->color}'>";
}
public function after()
{
echo "</div>";
}
}/**
? 字體大小裝飾器實現
? Class SizeDecorator
*/
class SizeDecorator implements Decorator
{
protected $size;
public function __construct($size)
{
$this->size = $size;
}
public function before()
{
echo "<dis style='font-size: {$this->size}px'>";
}
public function after()
{
echo "</div>";
}
}//實例化輸出類
echo->addDecorator(new ColorDecorator('red'));
//增加裝飾器
echo->Index();
//輸出<dis style='color: red'><dis style='font-size: 22px'>你好,我是裝飾器。</div></div>
將一個類的接口轉換成客戶希望的另一個接口,適配器模式使得原本的由于接口不兼容而不能一起工作的那些類可以一起工作。
場景:老代碼接口不適應新的接口需求,或者代碼很多很亂不便于繼續修改,或者使用第三方類庫。例如:php連接數據庫的方法:mysql,,mysqli,pdo,可以用適配器統一
//老的代碼
class User {private $name;
function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}}
//新代碼,開放平臺標準接口
interface UserInterface {
function getUserName();
}class UserInfo implements UserInterface {
protected $user;
function __construct($user) {
$this->user = $user;
}
public function getUserName() {
return $this->user->getName();
}}
$olduser = new User('張三');
echo $olduser->getName()."n";olduser);
echo $newuser->getUserName()."n";
關于“PHP中常見的開發模式有哪些及怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。