使用观察者模式处理错误信息
使用观察者模式处理异常信息
异常信息的捕获对编程测试有着重要的意义,这里结合观察者模式,探索如何处理异常信息。
关于观察者模式,如果还没有接触过的话,博客园有很多优秀的博友做了详细的 解释。笔者觉得,所谓观察者模式,必须有两个重要组成部分:一个主题对象,多个观察者。在使用的时候,我们可以将观察者像插头一样插到主题对象这个插座上,利用主题对象完成相应功能。
既然观察者要作为插头,必须要有一个统一的口径才能插到相同的插座上,因而先定义一个接口,Exception_Observer.php:
<span style="color: #000000;">php </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 定义的规范 </span><span style="color: #008000;">*/</span><span style="color: #0000ff;">interface</span><span style="color: #000000;"> Exception_Observer{ </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> update(Observer_Exception <span style="color: #800080;">$e</span><span style="color: #000000;">);} </span>?>
相对于众多观察者,我们首先应该关注唯一的主题对象,Observer_Exception.php:
<span style="color: #000000;">php</span><span style="color: #0000ff;">class</span> Observer_exception <span style="color: #0000ff;">extends</span> <span style="color: #0000ff;">Exception</span><span style="color: #000000;">{ </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #800080;">$_observers</span>=<span style="color: #0000ff;">array</span><span style="color: #000000;">(); </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">function</span> attach(Exception_Observer <span style="color: #800080;">$observer</span><span style="color: #000000;">){ self</span>::<span style="color: #800080;">$_observers</span>[]=<span style="color: #800080;">$observer</span><span style="color: #000000;">; } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> __construct(<span style="color: #800080;">$message</span>=<span style="color: #0000ff;">null</span>,<span style="color: #800080;">$code</span>=0<span style="color: #000000;">){ parent</span>::__construct(<span style="color: #800080;">$message</span>,<span style="color: #800080;">$code</span><span style="color: #000000;">); </span><span style="color: #800080;">$this</span>-><span style="color: #000000;">notify(); } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> notify(){ </span><span style="color: #0000ff;">foreach</span> (self::<span style="color: #800080;">$_observers</span> <span style="color: #0000ff;">as</span> <span style="color: #800080;">$observer</span><span style="color: #000000;">) { </span><span style="color: #800080;">$observer</span>->update(<span style="color: #800080;">$this</span><span style="color: #000000;">); } }}</span>
我们可以清楚地看到,静态变量$_observers用来放置插入的观察者,notify()用来通知所有观察者对象。
这里需要注意 $observer->update($this); 里面 $this 的用法,很多初学者会感到“原来 $this 也可以这么用啊”。
一个小问题: $_observers 不是静态变量可不可以? 这个问题我们后面回答。
定义两个观察者,原则上实现接口所定义的功能。
Email_Exception_Observer.php:
<span style="color: #0000ff;">class</span> Emailing_Exception_Observer <span style="color: #0000ff;">implements</span><span style="color: #000000;"> Exception_Observer{ </span><span style="color: #0000ff;">protected</span> <span style="color: #800080;">$_email</span>="[email protected]"<span style="color: #000000;">; </span><span style="color: #0000ff;">function</span> __construct(<span style="color: #800080;">$email</span>=<span style="color: #0000ff;">null</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">if</span> (<span style="color: #800080;">$email</span>!==<span style="color: #0000ff;">null</span>&&filter_var(<span style="color: #800080;">$email</span>,<span style="color: #000000;">FILTER_VALIDATE_EMAIL)) { </span><span style="color: #800080;">$this</span>->_email=<span style="color: #800080;">$email</span><span style="color: #000000;">; } } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> update(Observer_Exception <span style="color: #800080;">$e</span><span style="color: #000000;">){ </span><span style="color: #800080;">$message</span>="时间".<span style="color: #008080;">date</span>("Y-m-d H:i:s").<span style="color: #ff00ff;">PHP_EOL</span><span style="color: #000000;">; </span><span style="color: #800080;">$message</span>.="信息".<span style="color: #800080;">$e</span>->getMessage().<span style="color: #ff00ff;">PHP_EOL</span><span style="color: #000000;">; </span><span style="color: #800080;">$message</span>.="追踪信息".<span style="color: #800080;">$e</span>->getTraceAsString().<span style="color: #ff00ff;">PHP_EOL</span><span style="color: #000000;">; </span><span style="color: #800080;">$message</span>.="文件".<span style="color: #800080;">$e</span>->getFile().<span style="color: #ff00ff;">PHP_EOL</span><span style="color: #000000;">; </span><span style="color: #800080;">$message</span>.="行号".<span style="color: #800080;">$e</span>->getLine().<span style="color: #ff00ff;">PHP_EOL</span><span style="color: #000000;">; </span><span style="color: #008080;">error_log</span>(<span style="color: #800080;">$message</span>,1,<span style="color: #800080;">$this</span>-><span style="color: #000000;">_email); }}</span>
Logging_Exception_Observer.php:
<span style="color: #000000;">php </span><span style="color: #0000ff;">class</span> Logging_Exception_Observer <span style="color: #0000ff;">implements</span><span style="color: #000000;"> Exception_Observer{ </span><span style="color: #0000ff;">protected</span> <span style="color: #800080;">$_filename</span>="F:/logException.log"<span style="color: #000000;">; </span><span style="color: #0000ff;">function</span> __construct(<span style="color: #800080;">$filename</span>=<span style="color: #0000ff;">null</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">if</span> (<span style="color: #800080;">$filename</span>!==<span style="color: #0000ff;">null</span>&&<span style="color: #008080;">is_string</span>(<span style="color: #800080;">$filename</span><span style="color: #000000;">)) { </span><span style="color: #800080;">$thvis</span>->_filename=<span style="color: #800080;">$filename</span><span style="color: #000000;">; } } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> update(Observer_Exception <span style="color: #800080;">$e</span><span style="color: #000000;">){ </span><span style="color: #800080;">$message</span>="时间".<span style="color: #008080;">date</span>("Y-m-d H:i:s").<span style="color: #ff00ff;">PHP_EOL</span><span style="color: #000000;">; </span><span style="color: #800080;">$message</span>.="信息".<span style="color: #800080;">$e</span>->getMessage().<span style="color: #ff00ff;">PHP_EOL</span><span style="color: #000000;">; </span><span style="color: #800080;">$message</span>.="追踪信息".<span style="color: #800080;">$e</span>->getTraceAsString().<span style="color: #ff00ff;">PHP_EOL</span><span style="color: #000000;">; </span><span style="color: #800080;">$message</span>.="文件".<span style="color: #800080;">$e</span>->getFile().<span style="color: #ff00ff;">PHP_EOL</span><span style="color: #000000;">; </span><span style="color: #800080;">$message</span>.="行号".<span style="color: #800080;">$e</span>->getLine().<span style="color: #ff00ff;">PHP_EOL</span><span style="color: #000000;">; </span><span style="color: #008080;">error_log</span>(<span style="color: #800080;">$message</span>,3,<span style="color: #800080;">$this</span>-><span style="color: #000000;">_filename); }}</span>
设计完所有该有的主体对象和插件,我们做个小小的测试:
<span style="color: #000000;">php </span><span style="color: #0000ff;">require</span> 'Exception_Observer.php'<span style="color: #000000;">;</span><span style="color: #0000ff;">require</span> 'Observer_Exception.php'<span style="color: #000000;">;</span><span style="color: #0000ff;">require</span> 'Logging_Exception_Observer.php'<span style="color: #000000;">;</span><span style="color: #0000ff;">require</span> 'Emailing_Exception_Observer.php'<span style="color: #000000;">;Observer_Exception</span>::attach(<span style="color: #0000ff;">new</span><span style="color: #000000;"> Logging_Exception_Observer());</span><span style="color: #0000ff;">class</span> MyException <span style="color: #0000ff;">extends</span><span style="color: #000000;"> Observer_Exception{ </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> test(){ </span><span style="color: #0000ff;">echo</span> 'this is a test'<span style="color: #000000;">; } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> test1(){ </span><span style="color: #0000ff;">echo</span> "我是自定义的方法处理这个异常"<span style="color: #000000;">; }}</span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> MyException("出现异常,记录一下"<span style="color: #000000;">); } </span><span style="color: #0000ff;">catch</span> (MyException <span style="color: #800080;">$e</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">echo</span> <span style="color: #800080;">$e</span>-><span style="color: #000000;">getMessage(); </span><span style="color: #0000ff;">echo</span> "<ht></ht>"<span style="color: #000000;">; }</span>?>
本实例首先先加载观察者,其后进行其他操作。回到上面提出的问题, $_observers 可以不是静态变量吗?答案是不可以。如果 $_observers 不是静态变量,加载观察者的行为对后续操作没有影响。static让所有实例成员共享某个变量。即便类继承也同样有效。有兴趣的可以继续探索下static的神奇作用吧。
本例显示输出与一般情况无异,但不同的是已在自定义的文件下生成了相应的日志。虽然最后实现的功能再简单不过,很多人甚至可以用更少的代码更简单的方法实现,但是,在实现更加复杂系统的情况下,观察者模式给我们带来很大方便。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。
