CHAPTER 11 ■ PERFORMING AND REPRESENTING TASKS
$this->setStatus( self::LOGIN_WRONG_PASS, $user, $ip );
$ret = false;
break;
case 3:
$this->setStatus( self::LOGIN_USER_UNKNOWN, $user, $ip );
$ret = false;
break;
}
Logger::logIP( $user, $ip, $this->getStatus() );
return $ret;
}
Worried about security, the system administrators might ask for notification of failed logins. Once
again, you can return to the login method and add a new call:
if (! $ret ) {
Notifier::mailWarning( $user, $ip,
$this->getStatus() );
}
The business development team might announce a tie-in with a particular ISP and ask that a cookie
be set when particular users log in, and so on, and on.
These are all easy enough requests to fulfill but at a cost to your design. The Login class soon
becomes very tightly embedded into this particular system. You cannot pull it out and drop it into
another product without going through the code line by line and removing everything that is specific to
the old system. This isn’t too hard, of course, but then you are off down the road of cut-and-paste
coding. Now that you have two similar but distinct Login classes in your systems, you find that an
improvement to one will necessitate the same changes in the other, until inevitably and gracelessly they
fall out of alignment with one another.
So what can you do to save the Login class? The Observer pattern is a powerful fit here.
Implementation
At the core of the Observer pattern is the unhooking of client elements (the observers) from a central
class (the subject). Observers need to be informed when events occur that the subject knows about. At
the same time, you do not want the subject to have a hard-coded relationship with its observer classes.
To achieve this, you can allow observers to register themselves with the subject. You give the Login
class three new methods, attach(), detach(), and notify(), and enforce this using an interface called
Observable:
interface Observable {
function attach( Observer $observer );
function detach( Observer $observer );
function notify();
}
// ... Login class
class Login implements Observable {
private $observers;
//...
function __construct() {