Контейнер свойств

Контейнер свойств

Контейнер свойств (англ. property container) — фундаментальный шаблон проектирования, который служит для обеспечения возможности динамического расширения свойств уже созданного объекта класса.

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


Достоинства

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


Недостатки

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


Пример реализации контейнера свойств на PHP

Объявим интерфейс PropertyContainerInterface

interface PropertyContainerInterface{
    function setProperty($propertyName, $value);
    function updateProperty($propertyName, $value);
    function getProperty($propertyName, $value);
    function deleteProperty($propertyName, $value);
}


Напишем реализацию интерфейса.

class PropertyContainer implements PropertyContainerInterface{
    private $propertyContainer = [];

    function setProperty($propertyName, $value){
        $this->propertyContainer[$propertyName] = $value;
    }

    function updateProperty($propertyName, $value){
        if (!isset($this->propertyContainer[$propertyName])) 
        {
            throw new Exception("property {$propertyName} not found");
        }

        $this->propertyContainer[$propertyName] = $value;
    }
    
    function getProperty($propertyName, $value){
        return $this->propertyContainer[$propertyName];
    }

    function deleteProperty($propertyName, $value){
        unset($this->propertyContainer[$propertyName]);
    }

} 


Унаследуем реализованный класс контейнер с методами.

class BlogPost extent PropertyContainer{
    private $title;

    public function setTitle($title){
        $this->title = $title;
    }
}


Пример использования контейнера свойств.

$post = new BlogPost();

// присваиваем свойсво изначально объявленое в классе
$post->setTitle('Hello');

// присваиваем динамическое свойство объекту
$post->setProperty('view_count', 100);
$post->updateProperty('view_count', 200);
$post->getProperty('view_count');
$post->deleteProperty('view_count');