As I explained in the previous section, when a basic error login class was added to the message handling application, the independence of their objects was compromised; therefore, an alternative approach should be implemented to avoid this issue. For this reason, I’ll apply the Observer pattern, thus the application can retain the objects’ independence without sacrificing functionality. Here’s how he application now looks, after implementing the Observer pattern: // define the abstract 'MessageObserver' interface As you can see, the above application looks slightly different when compared to the previous incarnation. All the changes that I introduced are minor yet significant, therefore pay close attention to the following explanation. In order to apply the Observer pattern, first I defined a “MessageObserver” interface, which exposes only an abstract “displayStatus()” method. Next, I created a basic “ErrorLogger” class, which implements this interface and also inherits the previous method. Here’s where you can spot the first difference. This class actually won’t log any errors, but instead will display notices from the respective “MessageSaver” objects. So, where’s the advantage in defining the logger class like this? Well, by doing so, all the objects of type “MessageSaver” will be responsible only for saving messages to a text file, period. Any eventual errors will be sent to the observer object (in this case the “ErrorLogger” class), and only this object will decide the course of action to take. Do you now see how all the involved objects are decoupled from the whole application? I hope you do. Once the observer class was created, I redefined the “MessageSaver” class, in order to add the “addObserver()”,“removeObserver()” and “notifyObserver()” methods to it. As you may have guessed, the first two methods simply add and remove observer objects from the class in question, assuming that the application will implement eventually other observers. The “notifyObserver()” method loops over all the observers (for this example, I have only one) and calls their “displayStatus()” method, in this way showing all the notices that were sent by the “MessageSaver” object when trying to save an offending message. This condition is demonstrated by the “save()” method, which is listed below: public function save(){ At this point, the previous example allowed me to apply the Observer pattern, which results in the decoupling of all the pertinent objects. It also results in the implementation of a handy mechanism for reflecting all the objects' changes at the application’s core level, and without having to write convoluted code! Want to see how the application works, after coding the respective observer class? Right, here’s an example: try{ The above script displays the following message: ErrorLogger notified the following error message: Message As you can see, the “MessageObserver” class displays the above notification, since I passed an invalid message to the “MessageConverter” class. This demonstrates the power of the Observer pattern. As homework, try adding more observers to the “ErrorLogger” class, and see what happens in each case, so you gain a solid grasp of this pattern. It’s really fun! To wrap up In this first article, you learned how to apply the Observer pattern inside a simple PHP application. Of course, feel free to treat the source code like a starting example and introduce some improvements to it. It’s the best way to grasp the concepts for how this pattern works. In the next tutorial, I’ll show you how to apply the Observer pattern in a real-world case: server-side data validation. See you there!
blog comments powered by Disqus |
|
|
|
|
|
|
|