Reg.ru: домены и хостинг

Крупнейший регистратор и хостинг-провайдер в России.

Более 2 миллионов доменных имен на обслуживании.

Продвижение, почта для домена, решения для бизнеса.

Более 700 тыс. клиентов по всему миру уже сделали свой выбор.

Перейти на сайт->

Бесплатный Курс "Практика HTML5 и CSS3"

Освойте бесплатно пошаговый видеокурс

по основам адаптивной верстки

на HTML5 и CSS3 с полного нуля.

Начать->

Фреймворк Bootstrap: быстрая адаптивная вёрстка

Пошаговый видеокурс по основам адаптивной верстки в фреймворке Bootstrap.

Научитесь верстать просто, быстро и качественно, используя мощный и практичный инструмент.

Верстайте на заказ и получайте деньги.

Получить в подарок->

Бесплатный курс "Сайт на WordPress"

Хотите освоить CMS WordPress?

Получите уроки по дизайну и верстке сайта на WordPress.

Научитесь работать с темами и нарезать макет.

Бесплатный видеокурс по рисованию дизайна сайта, его верстке и установке на CMS WordPress!

Получить в подарок->

*Наведите курсор мыши для приостановки прокрутки.


Шаблон проектирования «Наблюдатель»

В этой статье мы поговорим о шаблоне проектирования под названием "Наблюдатель". Наблюдатель - это некто, кто следит за вашей активностью и при необходимости имеет возможность предпринять определенные действия в зависимости от вашей активности.

Аналогичный принцип заложен и в работу этого шаблона проектирования.

Данный шаблон следует применять в случаях, когда у нас есть зависимость "один ко многим" и некий объект должен быть изменен, когда происходят изменения с любым из других объектов.

В Википедии по этому поводу написано следующее:

Шаблон проектирования "Наблюдатель" - это поведенческий шаблон проектирования. Также известен как «подчинённые» (Dependents), «издатель-подписчик» (Publisher-Subscriber). Создает механизм у класса, который позволяет получать экземпляру объекта этого класса оповещения от других объектов об изменении их состояния, тем самым наблюдая за ними.

Данный шаблон проектирования - ключевая составляющая популярного архитектурного паттерна model–view–controller (MVC).

Для демонстрации работы этого шаблона давайте рассмотрим пример приложения, которое показывает курсы различных валют относительно доллара США. Подразумевается, что приложение показывает цену и также обновляет ее через определенные интервалы времени.

Прежде, чем мы начнем, давайте определим основные обязанности главного класса приложения (который в данном примере будет "Наблюдателем"):

- Наблюдатель должен иметь возможность добавлять новые валюты.
- Наблюдатель должен показывать статус / значение каждой валюты.

Теперь давайте его реализуем:


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>Исходная цена фунта: {$price}</p>";
    }

    public function update() {
        $this->price = $this->getPrice();
        echo "<p>Обновленная цена фунта: {$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>Исходная цена йены: {$price}</p>";
    }

    public function update() {
        $this->price = $this->getPrice();
        echo "<p>Обновленная цена йены: {$this->price}</p>";
    }

    public function getPrice() {
        return f_rand(120.52, 122.50);
    }
}

Ок, теперь все готово для того, чтобы собрать все воедино и запустить нашего Наблюдателя.

Собираем код вместе:


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>Исходная цена фунта: {$price}</p>";
    }

    public function update() {
        $this->price = $this->getPrice();
        echo "<p>Обновленная цена фунта: {$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>Исходная цена йены: {$price}</p>";
    }

    public function update() {
        $this->price = $this->getPrice();
        echo "<p>Обновленная цена йены: {$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();

Выполнение данного кода даст следующий результат:


Исходная цена фунта: 0.6

Исходная цена йены: 122

-------------

Обновленная цена фунта: 0.65346

Обновленная цена йены: 121.287809

-------------

Обновленная цена фунта: 0.671269

Обновленная цена йены: 121.300605

Вы можете видеть, что в этом коде мы обновили цены для всех ранее созданных валют и вывели их на экран.

Теперь давайте подумаем, как можно добавлять новые валюты в приложение с минимальными его изменениями.

Данные изменения касаются лишь процесса регистрации (добавления) новой валюты в наше приложение. Таким образом, наш клиентский код остается нетронутым, когда он вызывает функцию обновления цены в приложении.

Добавление новой валюты:


class Euro implements Currency {
    private $price;

    public function __construct($price) {
        $this->price = $price;
        echo "<p>Исходная цена евро: {$price}</p>";
    }

    public function update() {
        $this->price = $this->getPrice();
        echo "<p>Обновленная цена евро: {$this->price}</p>";
    }

    public function getPrice() {
        return f_rand(0.78, 0.85);
    }
}

Добавить новую валюту было очень просто, и теперь нам осталось лишь заставить нашего Наблюдателя ее отслеживать:


$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();

Вывод

Состояние любого объекта в объектно-ориентированном программировании очень важно, ведь вся работа приложения строится на взаимодействии между объектами.

Часто бывает необходимо, чтобы часть объектов была оповещена, когда происходят изменения в других объектах. В этом случае на помощь приходит шаблон пректирования "Наблюдатель".

Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!


Смотрите также:

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

CodeIgniter: жив или мертв?

CodeIgniter: жив или мертв?

Функции обратного вызова, анонимные функции и механизм замыканий

Функции обратного вызова, анонимные функции и механизм замыканий

Применение функции к каждому элементу массива

Применение функции к каждому элементу массива

Слияние массивов. Преобразование массива в строку

Слияние массивов. Преобразование массива в строку

Деструктор и копирование объектов с помощью метода __clone()

Деструктор и копирование объектов с помощью метода __clone()

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

PHP: Удаление элементов массива

PHP: Удаление элементов массива

Ключевое слово final (завершенные классы и методы в PHP)

Ключевое слово final (завершенные классы и методы в PHP)

50 классных сервисов, программ и сайтов для веб-разработчиков

50 классных сервисов, программ и сайтов для веб-разработчиков

Наверх