It seems like these interfaces are pretty much useless for any real world problem. Can someone enlighten me?
Interface
While abstract classes let you provide some measure of implementation, interfaces are pure templates. An interface
can only define functionality
; it can never implement it. An interface is declared with the interface keyword. It can contain properties and method declarations, but not method bodies.
Interface Use case
For example if you want to your project should support different databases . so that you can change your database in future its better to use interfaces that contains property procedures in class file with out altering objects
By itself, interfaces are not very useful
because You cannot create instances of interfaces but Interfaces are instrumental in enforcing object oriented design methodologies which in real sense makes your live easier as a programmer
because the foremost incentive for object oriented programming is encapsulation (You don't care how a capability is implemented. You, as a programmer, are exposed only to the interface. This is also a good way to watch after the system architecture)
SplSubject & SplObserver
Orthogonality is a virtue , One of objectives as programmers should be to build components that can be altered or moved with minimal impact on other components.
If every change you make to one component necessitates a ripple of changes elsewhere in the codebase, the task of development can quickly become a spiral of bug creation and elimination.
There is no special feature of SplSubject and SplObserver because thy are both interface to implement the Observer Design Pattern.
Observer pattern
The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems
- The Observer pattern defines an one-to-many dependency between a subject object and any number of observer objects so that when the subject object changes state, all its observer objects are notified and updated automatically.
- The Observer pattern essentially allows an unlimited number of objects to observe or listen to events in the observed object (or subject) by registering themselves. After observers are registered to an event, the subject will notify them when the event is fired.
- The subject handles this by storing an observer collection and iterating through it when the event occurs in order to notify each observer.
- Observer Pattern registers observers with a subject.
- You might have multiple observers. Subject must keep a list of registered observers and when event occurs it fires (provides notification) all registered observers.
- Unregister also possible when we do not need any observer.
Example 1. Interest Rate Notification System for a Loan
$loan = new Loan("Mortage", "Citi Bank", 20.5);
$loan->attach(new Online());
$loan->attach(new SMS());
$loan->attach(new Email());
echo "<pre>";
$loan->setIntrest(17.5);
Output
Online : Post online about modified Intrest rate of : 17.50
Send SMS : Send SMS to premium subscribers : 17.50
Send Email: Notify mailing list : 17.50
Example 2. Simple User Register Monitor
$users = new Users();
new Audit($users);
new Logger($users);
new Security($users);
$users->addUser("John");
$users->addUser("Smith");
$users->addUser("Admin");
Output
Audit : Notify Audit about John
Log : User John Create at Wed, 12 Dec 12 12:36:46 +0100
Audit : Notify Audit about Smith
Log : User Smith Create at Wed, 12 Dec 12 12:36:46 +0100
Audit : Notify Audit about Admin
Log : User Admin Create at Wed, 12 Dec 12 12:36:46 +0100
Security : Alert trying to create Admin
Advantage of Observer Design Pattern:
Main advantage is loose coupling between objects called observer and observable. The subject only know the list of observers it don’t care about how they have their implementation.All the observers are notified by subject in a single event call as Broadcast communication
Disadvantage of Observer Design Pattern:
- The disadvantage is that the sometime if any problem comes, debugging becomes very difficult because flow of control is implicitly between observers and observable we can predict that now observer is going to fire and if there is chain between observers then debugging become more complex.
- Another issue is Memory management when dealing with large observers
Common Classes
abstract class Observable implements SplSubject {
protected $_observers = [];
public function attach(SplObserver $observer) {
$id = spl_object_hash($observer);
$this->_observers[$id] = $observer;
}
public function detach(SplObserver $observer) {
$id = spl_object_hash($observer);
if (isset($this->_observers[$id])) {
unset($this->_observers[$id]);
}
}
public function notify() {
foreach ( $this->_observers as $observer ) {
$observer->update($this);
}
}
}
abstract class Observer implements SplObserver {
private $observer;
function __construct(SplSubject $observer) {
$this->observer = $observer;
$this->observer->attach($this);
}
}
Load Example Classes
class Loan extends Observable {
private $bank;
private $intrest;
private $name;
function __construct($name, $bank, $intrest) {
$this->name = $name;
$this->bank = $bank;
$this->intrest = $intrest;
}
function setIntrest($intrest) {
$this->intrest = $intrest;
$this->notify();
}
function getIntrest() {
return $this->intrest;
}
}
class Online implements SplObserver {
public function update(SplSubject $loan) {
printf("Online : Post online about modified Intrest rate of : %0.2f\n",$loan->getIntrest());
}
}
class SMS implements SplObserver {
public function update(SplSubject $loan) {
printf("Send SMS : Send SMS to premium subscribers : %0.2f\n",$loan->getIntrest());
}
}
class Email implements SplObserver {
public function update(SplSubject $loan) {
printf("Send Email: Notify mailing list : %0.2f\n",$loan->getIntrest());
}
}
User Register Example Classes
class Users extends Observable {
private $name;
function addUser($name) {
$this->name = $name;
$this->notify();
}
function getName() {
return $this->name;
}
}
class Audit extends Observer {
public function update(SplSubject $subject) {
printf("Audit : Notify Autify about %s\n", $subject->getName());
}
}
class Logger extends Observer {
public function update(SplSubject $subject) {
printf("Log : User %s Create at %s\n", $subject->getName(),date(DATE_RFC822));
}
}
class Security extends Observer {
public function update(SplSubject $subject) {
if($subject->getName() == "Admin")
{
printf("Security : Alert trying to create Admin\n");
}
}
}