Теперь я приведу еще один паттерн поведенческого проектирования в этой серии, который представляет собой паттерн наблюдателя. Наблюдатель означает, что кто-то наблюдает за вашей деятельностью, и вполне возможно, что наблюдатель предпримет какое-то действие в зависимости от вашей активности.
Та же концепция применима и к шаблону дизайна. Мы должны реализовать этот шаблон, когда у нас есть зависимость «один ко многим» между нашим объектом, и один объект должен быть изменен / уведомлен, когда какие-либо изменения были внесены в любой другой объект.
Википедия говорит то же самое в словах ниже:
Шаблон наблюдателя — это шаблон разработки программного обеспечения, в котором объект, называемый субъектом, ведет список своих зависимых, называемых наблюдателями, и автоматически уведомляет их о любых изменениях состояния, обычно вызывая один из их методов. Он в основном используется для реализации распределенных систем обработки событий. Шаблон Observer также является ключевой частью в привычном архитектурном шаблоне модель-представление-контроллер (MVC).
Чтобы подробнее узнать об этом шаблоне проектирования, я беру пример симулятора, который показывает стоимость различных валют по отношению к доллару США. Мы предполагаем, что симулятор показывает цену, а также обновляет цену через равные промежутки времени.
Прежде чем мы начнем, давайте определим обязанности основного класса симулятора (который ведет себя как наблюдатель в этом примере).
- Этот наблюдатель должен иметь возможность добавлять новую валюту, чтобы клиент мог добавить любое количество валют по своему желанию.
- Этот наблюдатель должен сохранить ссылку на все добавленные валюты.
- Этот наблюдатель должен показать статус / значение каждой зарегистрированной валюты.
В следующем разделе мы реализуем нашего наблюдателя:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
interface Observer {
public function addCurrency(Currency $currency);
}
class priceSimulator implements Observer {
private $currencies;
public function __construct() {
$this->currencies = array();
}
public function addCurrency(Currency $currency) {
array_push($this->currencies, $currency);
}
public function updatePrice() {
foreach ($this->currencies as $currency) {
$currency->update();
}
}
}
|
Если вы посмотрите на приведенный выше код, вы увидите, что он способен выполнять все обязанности, которые мы упоминали в предыдущем разделе.
Теперь у нас есть готовый наблюдатель. Теперь нам нужны разные валюты, которые мы можем добавить к этому наблюдателю, и тогда мы готовы идти. Давайте реализуем наши классы валют сейчас.
|
01
02
03
04
05
06
07
08
09
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
|
interface Currency {
public function update();
public function getPrice();
}
class Pound implements Currency {
private $price;
public function __construct($price) {
$this->price = $price;
echo «<p>Pound Original Price: {$price}</p>»;
}
public function update() {
$this->price = $this->getPrice();
echo «<p>Pound Updated Price : {$this->price}</p>»;
}
public function getPrice() {
return f_rand(0.65, 0.71);
}
}
class Yen implements Currency {
private $price;
public function __construct($price) {
$this->price = $price;
echo «<p>Yen Original Price : {$price}</p>»;
}
public function update() {
$this->price = $this->getPrice();
echo «<p>Yen Updated Price : {$this->price}</p>»;
}
public function getPrice() {
return f_rand(120.52, 122.50);
}
}
|
Мы все готовы собрать все вместе и запустить нашего наблюдателя.
Собираем все вместе
|
01
02
03
04
05
06
07
08
09
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
|
interface Observer {
public function addCurrency(Currency $currency);
}
class priceSimulator implements Observer {
private $currencies;
public function __construct() {
$this->currencies = array();
}
public function addCurrency(Currency $currency) {
array_push($this->currencies, $currency);
}
public function updatePrice() {
foreach ($this->currencies as $currency) {
$currency->update();
}
}
}
interface Currency {
public function update();
public function getPrice();
}
class Pound implements Currency {
private $price;
public function __construct($price) {
$this->price = $price;
echo «<p>Pound Original Price: {$price}</p>»;
}
public function update() {
$this->price = $this->getPrice();
echo «<p>Pound Updated Price : {$this->price}</p>»;
}
public function getPrice() {
return f_rand(0.65, 0.71);
}
}
class Yen implements Currency {
private $price;
public function __construct($price) {
$this->price = $price;
echo «<p>Yen Original Price : {$price}</p>»;
}
public function update() {
$this->price = $this->getPrice();
echo «<p>Yen Updated Price : {$this->price}</p>»;
}
public function getPrice() {
return f_rand(120.52, 122.50);
}
}
function f_rand($min=0,$max=1,$mul=1000000){
if ($min>$max) return false;
return mt_rand($min*$mul,$max*$mul)/$mul;
}
$priceSimulator = new priceSimulator();
$currency1 = new Pound(0.60);
$currency2 = new Yen(122);
$priceSimulator->addCurrency($currency1);
$priceSimulator->addCurrency($currency2);
echo «<hr />»;
$priceSimulator->updatePrice();
echo «<hr />»;
$priceSimulator->updatePrice();
|
Код выше выведет:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
Pound Original Price: 0.6
Yen Original Price : 122
————-
Pound Updated Price : 0.65346
Yen Updated Price : 121.287809
————-
Pound Updated Price : 0.671269
Yen Updated Price : 121.300605
|
Здесь вы видите, что мы обновили цены на все зарегистрированные валюты, и они отображаются в нашем симуляторе. Теперь мы рассмотрим, как мы можем добавить новые валюты в этот симулятор с незначительными изменениями.
Эта модификация включает в себя регистрацию валют только на симуляторе. Таким образом, наш клиентский код остается неизменным всякий раз, когда он вызывает обновление цены в нашем симуляторе.
Добавление новой валюты
Класс валюты
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
class Euro implements Currency {
private $price;
public function __construct($price) {
$this->price = $price;
echo «<p>Euro Original Price : {$price}</p>»;
}
public function update() {
$this->price = $this->getPrice();
echo «<p>Euro Updated Price : {$this->price}</p>»;
}
public function getPrice() {
return f_rand(0.78, 0.85);
}
}
|
Добавить новую валюту было легко и просто. Теперь все, что нам нужно сделать, это зарегистрировать эту новую валюту в нашем наблюдателе, и мы все сделали!
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
$priceSimulator = new priceSimulator();
$currency1 = new Pound(0.60);
$currency2 = new Yen(122);
$currency3 = new Euro(122);
$priceSimulator->addCurrency($currency1);
$priceSimulator->addCurrency($currency2);
$priceSimulator->addCurrency($currency3);
echo «<hr />»;
$priceSimulator->updatePrice();
echo «<hr />»;
$priceSimulator->updatePrice();
|
Вывод
Состояние любого объекта очень важно в объектно-ориентированном программировании, потому что все работает между объектами и их взаимодействием друг с другом. Часто бывает так, что несколько объектов должны быть уведомлены, когда происходят изменения в других объектах. Шаблон проектирования Observer можно использовать, когда один или несколько наблюдателей должны наблюдать за изменениями в предмете.
Не забудьте оставить свой отзыв ниже.