Use SPL quickly implement Observer design pattern

What is the SPL

SPL (Standard PHP Library) standard PHP library i.e., PHP 5 is on the object-oriented ability to enhance true portrayal, which consists of a series of built-in classes, interfaces and functions. SPL by the addition of the collection, the iterator, new exception type, file and data processing etc. to enhance the productivity of the PHP language. It also provides some very useful features, such as built-Observer design pattern this article to introduce.

This article describes how to use the SPL provided SplSubjectand SplObserverinterfaces as well as SplObjectStorageclasses, quickly realize Observer design pattern.

SplSubject and SplObserver Interface

Observer design pattern defines the dependencies among the many objects of one kind, when the object is viewed is changed, all depending objects are notified and updated automatically, but also between the observer and the objects observed They are loosely coupled. In this mode, there is a target (Subject) and the observer (Observer) two roles. Target character is observed object, hold and control certain state, any number of viewers may be viewed as a target, using the SPL SplSubjectinterface specification of the behavior character:

Interface Method SplSubject

Method Statement description
abstract public void attach ( SplObserver $observer ) Add (register) an observer
abstract public void detach ( SplObserver $observer ) Delete an observer
abstract public void notify ( void ) When the state changes, notify all observers

Observer role is when the target changes need to be informed of the object. SPL with SplObserverinterface specification behavior that role:

SplObserver Methods

Method Statement description
abstract public void update ( SplSubject $subject ) Receive notifications sent by the target when the target is changed; when the target call its attention notify()is called

The core idea of this design pattern is SplSubjectcalled when the object will change its state notify()method, this method is called once, by any previous attach()method of registering up SplObserverthe object will be to call its update()updated ways and means.

Why SplObjectStorage class

SplObjectStorageClass implements the set (as the object is ignored if the key data corresponding to) such a data structure mapping an object-key (Map) or object. Examples of this class like an array, but the object to which it is stored is unique. This feature will contribute a lot of power to quickly implement Observer design pattern, because we do not want to be registered multiple times with an observer. Another feature of this class is directly removed from the specified object, without the need to traverse or search the entire collection.

SplObjectStorageExamples of the class have been able to store only unique object, because of its SplObjectStorage::attach()implementation in a first determines whether the specified object has been stored:

Listing 1. SplObjectStorage :: attach () method of some source code

function attach($obj, $inf = NULL) 
{ 
   if (is_object($obj) && !$this->contains($obj)) 
   { 
       $this->storage[] = array($obj, $inf); 
   } 
}

Analog Case

Let us demonstrate the power of the SPL on the Observer design pattern through a simulation case. This case simulates a website user management module, which includes three main functions:

  • Add a user
  • To specify the user's password is changed to His appointed a new password
  • Reset their password when a user forgets a password

Every time after the completion of these functions, you need the password to the user. In addition to traditional sending Email this means to the user, we also need to send an SMS to the user's mobile phone, allowing them to more easily know what the password yes. Suppose our website there is information systems within a station, we call small piece of paper, after the user to change or reset the password, send a small note to them will make them happy.

After analysis, the case for using the Observer design pattern to solve, because the password to change the user's password to the user a variety of means - whether from scratch, users take the initiative to change or reset the system - as a foreign Relationship.

We decided to define a User class represents a user needs to achieve the three functions. This class is the Observer design pattern target (Subject) role. We also need a set of classes that implement functions using various means to send a new password to the user, these class acts as the Observer design mode observer (Observer) role.

After a simple analysis, we draw the UML class diagram:

UML class diagram simulation case

SPL_observer

The UML class diagrams, first, the definition of a class named User user simulation case. Although the actual site users have more properties, in particular usually you need ID to identify each user, but we have to highlight the theme of this article, leaving only the required property cases.

Listing 2. User class source code

<?php
 
class User implements SplSubject { 
 
   private $email; 
   private $username; 
   private $mobile; 
   private $password; 
   /** 
    * @var SplObjectStorage 
    */ 
   private $observers = NULL; 
 
   public function __construct($email, $username, $mobile, $password) { 
       $this->email = $email; 
       $this->username = $username; 
       $this->mobile = $mobile; 
       $this->password = $password; 
 
       $this->observers = new SplObjectStorage(); 
   } 
 
   public function attach(SplObserver $observer) { 
       $this->observers->attach($observer); 
   } 
 
   public function detach(SplObserver $observer) { 
       $this->observers->detach($observer);
   } 
 
   public function notify() { 
       $userInfo = array( 
           'username' => $this->username, 
           'password' => $this->password, 
           'email' => $this->email, 
           'mobile' => $this->mobile, 
       ); 
       foreach ($this->observers as $observer) { 
           $observer->update($this, $userInfo); 
       } 
   } 
 
   public function create() { 
       echo __METHOD__, PHP_EOL; 
       $this->notify(); 
   } 
 
   public function changePassword($newPassword) { 
       echo __METHOD__, PHP_EOL; 
       $this->password = $newPassword; 
       $this->notify(); 
   } 
 
   public function resetPassword() { 
       echo __METHOD__, PHP_EOL; 
       $this->password = mt_rand(100000, 999999); 
       $this->notify(); 
   } 
 
}

User class in order to act as a target role, we need to implement SplSubjectan interface, and in accordance with the law to achieve interface attach(), detach()and notify()it must be implemented. Please note that due to the SplSubjectinterface, attach() 和detach() 的参数都使用了类型提示(of the type hinting ),在实现这两个方法时,也**不能**省略参数前面的类型。we also used the $observersexample of a property holds SplObjectStoragean object, used to store up all the registered observers.

Indeed, an array will solve the problem, but will soon be discovered, use the SplObjectStoragedelete an observer how easy it is to implement directly entrusted to the following SplObjectStorageobjects! Yes, most do not need to use the original forsentence or in an array to traverse the observer array_searchfunction, to get a line.

Next to act as an observer role in the three categories were defined to send information. For simplicity, we just pretend to send information through text output. You can even pretend that still need to know the user's information. You can look at SplObserverthe interface update()method signature, how frustrating it can not accept the target character by calling its notifyparameters given time () method to send notifications. If you try to rewrite update()plus second parameter method, you will get a similar

Fatal error: Declaration of EmailSender :: update () must be compatible with that of SplObserver :: update () is the error code execution terminates.

In fact, when the target held by the state (in this case, is the user's password) is updated, how to notify the viewer in two ways. "Pull" method and the "push" approach. SPL using the "pull" method, the viewer need to refer to the destination (as a update()method of parameter passing) to access its properties. "Pull" approach needs to let the viewer know more about what goals have attributes, which increases their degree of coupling. And also the theme of the observer door wide open, contrary to encapsulation. The solution is to provide a series of getter methods in the target, as getPassword()to make the viewer get the user's password.

Although the "pull" approach may be considered to be more correct, but we think the user to make the theme of "push" information to come more easily. Since rewriting by update()adding the second parameter when the method is not feasible, then proceed from the other direction. Fortunately, PHP has such a characteristic in a method call, as long as the specified given parameter (argument) is not less than a mandatory parameter is defined (no parameter default values), the error will not PHP. A number of parameters passed in the method, by func_num_args() 函数获取;extra parameters can func_get_arg()function to read. Note that this function is counted from 0, i.e., 0 represents an argument. Using this trick, update()the method can func_get_arg(1)receive one of an array of user information, with this array, you can know who sent the message, what is the new password. To save space, and information transmitted three classes is very similar, only one of which is given below of the source code, complete source code can be downloaded attachments obtained herein.

Listing 3. Email_Sender class source code

<?php 
 
class EmailSender implements SplObserver { 
 
   public function update(SplSubject $subject) { 
       if (func_num_args() === 2) { 
           $userInfo = func_get_arg(1); 
           echo "向 {$userInfo['email']} 发送电子邮件成功。内容是:你好 {$userInfo['username']}" . 
           "你的新密码是 {$userInfo['password']},请妥善保管", PHP_EOL; 
       } 
   } 
 
}

Finally, we write a test script test.php. The recommended way to use the CLI php – f test.phpto execute the script, but the provision of the Content-Typeresponse header field text/plain, the browser should be able to see the results displayed line by line (because there is no use <br />to make line breaks but constant use PHP_EOL, so do not set the Content-Typewords It can not correctly display the branch).

Listing 4. Test Script

<?php
 
header('Content-Type: text/plain'); 
 
function __autoload($class_name) { 
   require_once "$class_name.php"; 
} 
 
$email_sender = new EmailSender(); 
$mobile_sender = new MobileSender(); 
$web_sender = new WebsiteSender(); 
 
$user = new User('[email protected]', '张三', '13610002000', '123456'); 
 
// 创建用户时通过 Email 和手机短信通知用户
$user->attach($email_sender); 
$user->attach($mobile_sender); 
$user->create($user); 
echo PHP_EOL; 
 
// 用户忘记密码后重置密码,还需要通过站内小纸条通知用户
$user->attach($web_sender); 
$user->resetPassword(); 
echo PHP_EOL; 
 
// 用户变更了密码,但是不要给他的手机发短信
$user->detach($mobile_sender); 
$user->changePassword('654321'); 
echo PHP_EOL;

Listing 5. Running results

User::create 
向 [email protected] 发送电子邮件成功。内容是:你好张三你的新密码是 123456,请妥善保管
向 13610002000 发送短消息成功。内容是:你好张三你的新密码是 123456,请妥善保管
 
 User::resetPassword 
向 [email protected] 发送电子邮件成功。内容是:你好张三你的新密码是 363989,请妥善保管
向 13610002000 发送短消息成功。内容是:你好张三你的新密码是 363989,请妥善保管
这是 1 封站内小纸条。你好张三,你的新密码是 363989,请妥善保管
 
 User::changePassword 
向 [email protected] 发送电子邮件成功。内容是:你好张三你的新密码是 654321,请妥善保管
这是 1 封站内小纸条。你好张三,你的新密码是 654321,请妥善保管

We see that user Joe Smith through a variety of means to know what his password Yes.

Conclusion

For experienced developers, even without the use of SPL can also be easily Observer design pattern, but use SPL to bring greater efficiency, especially in combined SplObjectStorageafter registration and deletion of the observer by its proxy instance is completed. Although the use of "push" update the Observer, SplObserverthe update()method only accepts one parameter appears to fly in the ointment, or SPL built Observer design pattern support only through "pull mode" get notice, but by tips presented in this article can be make up. Therefore, SPL on the rapid realization Observer design patterns become the first choice.

Transfer from https://www.ibm.com/developerworks/cn/opensource/os-cn-observerspl/#ibm-pcon

Guess you like

Origin www.cnblogs.com/martini-d/p/li-yong-spl-kuai-su-shi-xian-observer-she-ji-mo-sh.html