Библиографическое описание:

Лясин Д. Н., Симонова О. Н. Реализация архитектурного шаблона MVC с использованием шаблона проектирования «Наблюдатель» на языке PHP // Молодой ученый. — 2014. — №6. — С. 108-111.

В статьерассматриваются особенности реализации и пример использования архитектурного шаблона MVCи шаблона «наблюдатель» для разработки веб-приложений на языке PHP.

Ключевыеслова: архитектурный шаблон, шаблон проектирования, MVC, наблюдатель, веб-приложение.

Современные веб-приложения должны решать множество прикладных задач, требования к ним постоянно растут, они быть надежными, эффективными, обеспечивать простоту модификации и масштабирования. Поэтому проблема разработки оптимальной архитектуры веб-приложений в настоящее время очень актуальна.

При разработке серверных веб-приложений на языке PHP все чаще применяется объектно-ориентированный подход с использованием архитектурного шаблона MVC (от англ. Model-View-Controller). Этот шаблон предполагает разделение программной системы на несколько компонентов, называемых модель (Model), вид (View) и контроллер (Controller), благодаря чему бизнес-логика приложения отделяется от пользовательского интерфейса. Такое приложение проще изменять, масштабировать, тестировать и сопровождать.

Реализовать взаимодействие между моделью и видом можно различными способами. Часто для этой цели используется поведенческий шаблон проектирования «наблюдатель» (Observer). Он позволяет классу-наблюдателю (observer) получать оповещения от класса-наблюдаемого (observable) об изменении своего состояния, реализуя тем самым схему взаимодействия «издатель-подписчик». В качестве наблюдателя в шаблоне MVC выступает вид (или несколько видов), а в качестве наблюдаемого — модель. Виды регистрируются в модели, которая оповещает их об изменении своего состояния. После получения оповещения виды извлекают из модели необходимые данные и динамически генерируют веб-страницу.

Эффективно реализовать шаблон «наблюдатель» на языке PHP можно с использованием стандартной библиотеки PHP (Standard PHP Library, SPL), которая была введена в PHP5 [1]. Для этого используются следующие классы и интерфейсы, предоставляемые SPL:

SplSubject — интерфейс, предназначенный для наследования классом-наблюдаемым. Интерфейс объявляет следующие абстрактные методы:

SplSubject::attach(SplObserver$observer) — метод, позволяющий зарегистрировать объект-наблюдатель для последующей отправки ему оповещений;

SplSubject::detach(SplObserver$observer) — метод, удаляющий наблюдателя из списка зарегистрированных;

SplSubject::notify(void) — метод, который нужно вызывать для оповещения зарегистрированных наблюдателей об изменении своего состояния.

SplObserver — интерфейс, предназначенный для наследования классом-наблюдателем. Он объявляет единственный абстрактный метод SplSubject::update(), который должен быть определен в наблюдателе. Этот метод будет вызываться, когда объект класса SplSubject вызовет метод notify().

SplObjectStorage — класс, позволяющий сохранять в контейнере и удалять из контейнера объекты классов-наблюдателей при помощи методов attach() и detach().

Рассмотрим пример PHP-приложения, построенного на основе архитектурного шаблона MVC с применением шаблона «наблюдатель» для реализации взаимодействия модели и вида.

Диаграмма UML, иллюстрирующая взаимосвязи между классами, приведена на рисунке 1.

Рис. 1. Диаграмма классов, реализующих шаблон MVC с использованием шаблона «наблюдатель»

Базовый класс Model, который будет являться родительским для всех моделей приложения, определяется следующим образом:

class Model implements SplSubject

{

            private $storage;

            public $status;

            public function __construct($server, $user, $pass, $base)

            {

                        $this->storage = new SplObjectStorage();

            }

            function attach(SplObserver $observer)

            {

                        $this->storage->attach($observer);

            }

            function detach(SplObserver $observer)

            {

                        $this->storage->detach($observer);

            }

            function notify()

            {

                        foreach($this->storage as $obj)

{

                                   $obj->update($this);

                        }

            }

}

Классы моделей, реализующие действия, связанные с предметной областью приложения, являются потомками базового класса Model. Например, для раздела сайта, в котором можно просматривать и редактировать список подразделений организации, существуют класс Model_editPlaceInfo:

class Model_editPlaceInfo extends Model

{

//...

}

Класс View, который будет являться родительским для всех видов приложения, наследуется от класса Observer, который в свою очередь наследует интерфейс SplObserver:

abstract class Observer implements SplObserver

{

            function update(SplSubject $subject)

            {

                        $this->doUpdate($subject);

            }

            abstract function doUpdate(Model $model);

}

class View extends Observer

{

            function doUpdate(Model $model)

{

                        //...

            }

}

Классы видов, которые генерируют веб-страницы и передают их пользователю для отображения в браузере, являются потомками класса View. Например:

class View_editPlaceInfo extends View

{

             functiondoUpdate(Model $model)

            {

                        //...

            }

}

Непосредственное создание веб-страниц производится в методе doUpdate(). Он получает указатель на объект модели, из которой он может извлечь все данные, необходимые для отображения на странице.

Запросы пользователя веб-ресурса обрабатываются с использованием шаблона Front Controller [2], который обеспечивает единую точку обработки всех входящих запросов. После анализа URL, полученного в запросе пользователя, Front Controller определяет, какой из имеющихся контроллеров MVC необходимо использовать для его выполнения, и создает объект соответствующего класса. Front Controller также определяет действие, которое контроллер должен выполнить, и вызывает соответствующий метод, например action_getPlaceInfo(). В конструкторе контроллера __construct() создаются экземпляры классов модели (Model_editPlaceInfo) и вида (View_editPlaceInfo). Далее контроллер, в соответствии с логикой работы шаблона «наблюдатель», регистрирует вид в модели путем вызова метода attach():

$model=new Model_editPlaceInfo($params["server"], $params["user"], $params["pass"], $params["base"]);  

$view=new View_editPlaceInfo();

$model->attach($view);

Теперь во всех классах моделей, являющихся потомками класса Model, при каждом изменении состояния достаточно вызвать метод notify(). Все зарегистрированные виды получат оповещение, извлекут из модели необходимые данные, сгенерируют веб-страницу и передадут ее пользователю.

Изменяя реализацию классов вида, можно менять способ отображения данных для пользователя и внешнее оформление веб-страниц сайта. Изменяя классы моделей, можно менять логику работы приложения, способ хранения данных и т. д. Использование шаблона «наблюдатель» позволяет сделать модели и виды независимыми. Это значительно упрощает разработку и модификацию приложения, а также позволяет избежать множества ошибок.

Построение веб-приложения на основе объектно-ориентированного подхода с применением архитектурного шаблона MVC и поведенческого шаблона проектирования «наблюдатель» улучшает структурированность, масштабируемость и надежность программной системы, облегчает ее модификацию и сопровождение.

Литература:

1.      http://www.php.net/manual/ru/book.spl.php

2.      http://www.oracle.com/technetwork/java/frontcontroller-135648.html

3.      Зандстра М. PHP. Объекты, шаблоны и методики программирования. М.: Вильямс, 2011.

Обсуждение

Социальные комментарии Cackle