It seems like these interfaces are pretty much useless for any real world problem. Can someone enlighten me?
界面
虽然抽象类允许您提供一些实现措施,但接口是纯模板。一个interface
只能define functionality
;它永远无法实现它。使用 interface 关键字声明接口。它可以包含属性和方法声明,但不能包含方法体。
接口用例
例如如果你想你的项目应该支持不同的数据库。以便您将来可以更改数据库,最好使用在类文件中包含属性过程的接口而不更改对象
By itself, interfaces are not very useful
因为您不能创建接口的实例,但接口有助于实施面向对象的设计方法which in real sense makes your live easier as a programmer
,因为面向对象编程的首要动机是封装(您不关心功能是如何实现的。作为程序员,您只暴露于界面。这也是系统架构后观察的好方法)
SplSubject & SplObserver
正交性是一种美德,程序员的目标之一应该是构建可以更改或移动的组件,而对其他组件的影响最小。
如果您对一个组件所做的每一次更改都需要在代码库的其他地方进行一系列更改,那么开发任务很快就会变成一个螺旋式的错误创建和消除。
SplSubject和SplObserver没有特殊功能,因为它们都是interface to implement the Observer Design Pattern.
观察者模式
观察者模式是一种软件设计模式,其中一个称为主体的对象维护其依赖项列表,称为观察者,并自动通知他们任何状态更改,通常通过调用他们的方法之一。主要用于实现分布式事件处理系统
- 观察者模式定义了一个主题对象和任意数量的观察者对象之间的一对多依赖关系,这样当主题对象改变状态时,它的所有观察者对象都会自动得到通知和更新。
- 观察者模式本质上允许无限数量的对象通过注册自己来观察或监听被观察对象(或主题)中的事件。观察者注册到事件后,主体将在事件触发时通知他们。
- 主体通过存储观察者集合并在事件发生时迭代它以通知每个观察者来处理此问题。
- 观察者模式将观察者注册到一个主题。
- 您可能有多个观察者。主体必须保留已注册观察者的列表,并且当事件发生时,它会触发(提供通知)所有已注册的观察者。
- 当我们不需要任何观察者时,也可以取消注册。
示例 1. 贷款利率通知系统
$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);
输出
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
示例 2. 简单的用户注册监视器
$users = new Users();
new Audit($users);
new Logger($users);
new Security($users);
$users->addUser("John");
$users->addUser("Smith");
$users->addUser("Admin");
输出
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
观察者设计模式的优点:
主要优点是称为观察者和可观察对象之间的松散耦合。主体只知道观察者的列表,并不关心他们是如何实现的。所有观察者都由主体在单个事件调用中作为广播通信通知
观察者设计模式的缺点:
- 缺点是有时如果出现任何问题,调试会变得非常困难,因为控制流隐含在观察者和可观察者之间,我们可以预测现在观察者将要触发,如果观察者之间存在链,那么调试会变得更加复杂。
- 另一个问题是处理大型观察者时的内存管理
普通类
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);
}
}
加载示例类
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());
}
}
用户注册示例类
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");
}
}
}