观察者模式

什么是观察者模式?

 

观察者设计模式能够更便利地创建查看目标对象状态的对象,并且提供与核心对象非耦合的指定功能性。

该模式非常简单:一个对象通过添加一个方法(该方法允许另一个对象,即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。

 

UML

该图详细说明了一个使用观察者设计模式的类设计:

4.png

下面是对上图的说明:

1.MyObject是可观察对象,它包含一个名为observers的观察者保护数组。公共方法addObserver()接受一个观察者的实例并将其存储在观察者数组内。

2.doSomething()公共方法会被调用,这个方法对MyObject应用状态变化。随后,notify()公共方法会被调用,这个方法可遍历循环观察者数组。

3.MyObjectObserver具有一个名为change()的公共方法,该方法接受MyObject的一个实例。这个特定的观察者接下来会对MyObject的内容执行某些操作。当在观察者数组中找到特定的观察者时,MyObject的notify()方法会直接调用change()方法。

使用实例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

<?php 

interface Observable{ 

    function attach( Observer $observer ); 

    function detach( Observer $observer ); 

    function notify(); 

   

   

class login implements Observable{ 

    const LOGIN_USER_UNKNOW = 1; 

    const LOGIN_WRONG_PASS = 2; 

    const LOGIN_ACCESS = 3; 

    private $status = array(); 

    private $observers = array(); 

   

    public function setStatus( $status, $user, $ip ) { 

        $this->status = array( $status, $user, $ip ); 

    

    public function getStatus() { 

        return $this->status; 

    

    public function handleLogin( $user, $pass, $ip ) { 

        switch ( mt_rand( 1, 3 ) ) { 

        case 1: 

            $this->setStatus( self::LOGIN_USER_UNKNOW, $user, $ip ); 

            $ret = false; 

            break

        case 2: 

            $this->setStatus( self::LOGIN_WRONG_PASS, $user, $ip ); 

            $ret = false; 

            break

        case 3: 

            $this->setStatus( self::LOGIN_ACCESS, $user, $ip ); 

            $ret = true; 

            break

        

        $this->notify(); 

        return $ret

    

   

   

    public function attach( Observer $observer ) { 

        $this->observers[] = $observer

    

   

    public function detach( Observer $observer ) { 

        $newObservers = array(); 

        foreach ( $this->observers as $obs ) { 

            if ( $obs !== $observer

                $newObservers[] = $obs

        

        $this->observers = $newObservers

    

   

    public function notify() { 

        foreach ( $this->observers as $obs ) { 

            $obs->update( $this ); 

        

    

   

interface Observer{ 

    function update( Observable $observable ); 

   

class SecurityMonitor implements Observer{ 

    function update( Observable $observable ) { 

        $status = $observable->getStatus(); 

        if($status[0] == Login::LOGIN_WRONG_PASS){ 

            echo __CLASS__.":".$status[1]."于".$status[2]."登录失败"

        

    

   

$login = new Login(); 

$login->attach(new SecurityMonitor()); 

$login->handleLogin('XXX','XXX','127.0.0.1'); 

?> 

出错时的运行结果: 

SecurityMonitor:XXX于127.0.0.1登录失败[Finished in 0.1s]

代码中可以看到login对象主动添加SecurityMonitor对象观察。这样要调用Login::getStatus(),SecurityMonitor类就必须了解更多信息。虽然调用发生于一个ObServable对象上,但无法保证对象也是一个Login对象。为解决这个问题,有一个办法:断续保持ObServable接口的通用性,由ObServer类负责保证它们的主体是正确的类型。它们甚至能将自己添加到主体上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值