소행성이야기

[디자인패턴] 객체지향 php Observer Pattern (옵저버 패턴)

소행성왕자 2018. 7. 13. 17:04

[디자인패턴] 객체지향 php Observer Pattern (옵저버 패턴)


디자인 패턴 자체는 소프트웨어 설계에서 일반적으로 발생하는 문제에 대한 반복 가능한 솔루션이며,

그 중 하나는 Observer Pattern이며 일반적으로 한 객체의 변경이 하나 또는 여러 객체의 변경을 필요로하는 두 가지 측면의 추상화에 적용됩니다.

Laravel 과 같은 최신 PHP 프레임 워크는 Observer Pattern 을 포함한 여러 디자인 패턴을 사용합니다.

원칙을 알고 있어야하며 왜 이러한 패턴을 사용하여 디자인 패턴으로 가장 잘 해결할 수있는 비슷한 문제에 직면했을 때

효과적으로 적용 할 수 있습니다.


Observer Pattern 은 하나의 객체가 상태를 변경하면 모든 종속 객체가 

자동으로 통지되고 업데이트되도록 객체 간의 일대 다 의존성을 정의합니다. 


표준 PHP 라이브러리 인터페이스를 제공 

SplObserver 및 SplSubject PHP에서 Observer Pattern 을 구현하기위한 표준 템플릿으로합니다.


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
<?php
 
interface SplSubject  {
 
        /**
         * Attach an SplObserve
         * @param SplObserver $observer
         * @return void 
         */
        public function attach (SplObserver $observer);
 
        /**
         * Detach an observer
         * @param SplObserver $observe
         * @return void
         */
        public function detach (SplObserver $observer);
 
        /**
         * Notify an observer
         * @return void 
         */
        public function notify ();
 
}
 
interface SplObserver  {
 
        /**
         * Receive update from subject
         * @param SplSubject $subject
         * @return void 
         */
        public function update (SplSubject $subject);
 
}
cs


위에 정의 된 인터페이스에서 구현할 수있는 네 가지 메소드가 있으며 이들은 관찰자 패턴의 기본 구성 요소입니다.

함수 attach () 는 관찰자 (구독자)를 주제 (발행자)에 등록하거나 연관시킬 수있는 방법을 제공하고

detach () 는 관심없는 관찰자를 게시자로부터 분리하는 데 사용됩니다.

메소드 notify ()는 모든 가입 된 관찰자에게 각 관찰자에 대해 update () 를 호출하는 상태 변경을 통지합니다.


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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<?php
 
class Publisher implements \SplSubject
{
    /**
     * @var array
     */
    protected $linkedList = array();
 
    /**
     * @var array
     */
    protected $observers = array();
 
 
    /**
     *
     * @param string
     */
 
    protected $name;
 
    /**
     *
     * @param string
     */
 
    protected $event;
 
 
    public function __construct($name)
    {
 
        $this->name = $name;
    }
 
    /**
     *  Associate an observer
     *
     * @param SplObserver $observer
     * @return Publisher;
     */
 
    public function attach(SplObserver $observer)
    {
        $observerKey = spl_object_hash($observer);
        $this->observers[$observerKey= $observer;
        $this->linkedList[$observerKey= $observer->getPriority();
        arsort($this->linkedList);
    }
 
    /**
     * @param SplObserver $observer
     * @return void
     */
    public function detach(SplObserver $observer)
    {
        $observerKey = spl_object_hash($observer);
        unset($this->observers[$observerKey]);
        unset($this->linkedList[$observerKey]);
    }
 
    /**
     * @return void
     */
    public function notify()
    {
        foreach ($this->linkedList as $key => $value) {
            $this->observers[$key]->update($this);
        }
    }
 
    /**
     * Set or update event 
     *
     * @param $event
     * @return void
     */
    public function setEvent($event)
    {
        $this->event = $event;
        $this->notify();
    }
 
    /**
     * @return string
     */
    public function getEvent()
    {
        return $this->event;
    }
 
    public function getSubscribers()
    {
        return $this->getSubscribers();
    }
 
}
 
 
 
 
class Observer implements \SplObserver
{
    /**
     * @var  string
     */
    protected $name;
 
    /**
     * @var int
     */
    protected $priority = 0;
 
 
    /**
     * Accepts observer name and priority, default to zero
     */
    public function __construct($name$priority=0)
    {
        $this->name =$name;
        $this->priority =$priority;
    }
 
    /**
     * Receive update from subject and print result
     *
     * @param SplSubject $publisher
     * @return void
     */
    public function update(SplSubject $publisher){
 
        print_r($this->name.': '$publisher->getEvent(). PHP_EOL);
 
    }
 
    /**
     * Get observer priority
     * 
     * @return int
     */
    public  function getPriority(){
        return $this->priority;
    }
 
}
cs


우리의 관찰자 인스턴스는 관찰자 이름과 우선 순위라는 두 개의 인수를받습니다. 그런 다음 SplSubject 를 인수로 받아들이고 getEvent ()를 호출 하여 결과를 콘솔에 출력하는 함수 update () 를 구현합니다 .


사용법

슬랙 (Slack) 팀에 이벤트를 브로드 캐스트한다고 가정 해 봅시다.

일부는 휴가 중이며 메일을 통해서만 접근 할 수 있습니다.

또한 이벤트의 실시간 피드를 사무실에있는 대시 보드 화면에 표시하고자합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
 
$noty = new Publisher('NotificationPublisher');
$email = new Observer('EmailObserver'50);
$slack = new Observer('SlackObserver'10);
$dashboard = new Observer('DashboardObserver',30);
 
// Attach observers
$noty->attach($email);
$noty->attach($slack);
$noty->attach($dashboard);
// Set event that will be broadcasted
$noty->setEvent("Server LNX109 is going down");
cs


출력되는 결과는 아래와 같습니다.

1
2
3
4
5
EmailObserver: Server LNX109 is going down
DashboardObserver: Server LNX109 is going down
SlackObserver: Server LNX109 is going down
 
cs