Паттерн проектирования Приспособленец (Flyweight) на PHP 11.02.2011

Flyweight
Перед прочтением ознакомьтесь с введением в паттерны проектирования на PHP, в котором описаны принятые соглашения и понятия. Данная статья дополняется с некоторой периодичностью, так что если вы ее читали ранее, не факт что данные не изменились.

Приспособленец (Flyweight) относиться к классу структурных паттернов. Он используется для эффективной поддержки множества мелких объектов.

В некоторых приложения использование множества мелких объектов могло бы оказаться весьма полезным, однако прямая реализация ведет к чудовищному перерасходу ресурсов. Попробую объяснить это на примере интернет магазина, в котором мы будем продавать крутые дизайнерские подушки. С покупателями у нас не возникает проблем (так как подушки крутые), и список продаж все растет и растет. А так как это тешит наше самолюбие, вводить постраничность мы не спешим. И вот наступает тот момент, когда страница грузится  достаточно долго, чтобы мы успели не только заскучать, но и совершить вечерний променад. Мы достигаем точки кипения и с большой неохотой пытаемся оптимизировать нашу архитектуру. Она из себя представляет собой набор объектов-продаж, включающего объект-покупатель и набор объектов-товаров. Где каждый объект-товар это совокупность таких параметров, как: артикул подушки, цвет подушки, цена, скидка.

Получается, что на каждую запись о продаже инстанцируется минимум 2 объекта (в зависимости от количества купленных подушек). В текущей реализации, порождение такого количества объектов излишне. Путем не сложных манипуляций можно объединить объект-покупатель и объект-товар в один объект продажа. На этом можно не останавливаться и свести все к одному объекту продажи. 

Внося такие изменения мы не только теряем в гибкости и расширяемости, но и можем погрязнуть в устранении зависимостей. Решением этой проблемы может стать паттерн приспособленец.

Паттерн приспособленец позволяет повторно использовать мелкие объекты в различном контексте. В итоге мы сможем использовать в различных объектах-продажах одни и теже объекты-покупатели и объекты-товары. Как это работает на примере объекта-товара. У нас есть набор параметров (артикул подушки, цвет подушки, цена, скидка), которые полностью характеризуют этот товар. Соответственно, если у нас было несколько покупателей, которые выбрали одну и туже модель подушки, одного и того же цвета и попали под одну и туже скидку, то итоговые объекты-товары будут полностью идентичны. В итоге мы можем использовать один и тот же объект сразу в нескольких местах, что позволит сэкономить нам немного памяти. При достаточно большом количестве мелких объектов с малым количеством различающихся признаков, мы сможем получить весьма существенную экономию ресурсов. Итак, как структурно выглядит паттерн:

Flyweight (Приспособленец)

Где:

FlyweightFactory — модифицированный паттерн фабрика, для создания приспособленцев. Методу getFlyweight передаются признаки, по которым будет создан новый, либо найден и возвращен уже готовый объект.

Flyweight — абстрактный класс приспособленцев

ConcreteFlyweight — конкретная реализация приспособленца, которая будет замещать собой одинаковые мелкие объекты.

UnsharedFlyweight — реализация приспособленца, который не может быть разделен.

  1. class FlyweightFactory
  2. {
  3.     protected static $_flyweigthsarray();
  4.  
  5.     /**
  6.      * @param string $key
  7.      * @return Flyweight
  8.      */
  9.  
  10.     public static function getFlyweight($key)
  11.     {
  12.         // key может быть не только строкой, но и любым другим типом,
  13.         // в таком случае необходим иной способ поиска созданных приспособленцев
  14.  
  15.         if (! isset(self::$_flyweigths[$key])) {
  16.             // здесь могут быть условия, когда создавать обычного приспособленца,
  17.             // а когда возвращать неделимого
  18.  
  19.             self::$_flyweigths[$key] = new ConcreteFlyweight();
  20.         }
  21.  
  22.         return self::$_flyweigths[$key];
  23.     }
  24. }
  25.  
  26. abstract class Flyweight
  27. {
  28.     /**
  29.      * @var mixed внутреннее состояние
  30.      */
  31.  
  32.     protected $_intrinsicStatenull;
  33.  
  34.     /**
  35.      * @param mixed $extrinsicState
  36.      *  внешнее состояние, передаваемое в приспособленец (контекст)
  37.      */
  38.  
  39.     public function Operation($extrinsicState)
  40.     {
  41.         //...
  42.     }
  43. }
  44.  
  45. class ConcreteFlyweight extends Flyweight {}
  46. class UnsharedFlyweight extends Flyweight {}

Скачать исходный код можно тут.

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


, , , , , ,


Похожие статьи


Добавить комментарий