printСтруктурирующие паттерны

printПриспособленец

Flyweight

Назначение
Использует разделение для эффективной поддержки множества мелких объектов.

Результаты
При использовании приспособленцев не исключены затраты на передачу, поиск или вычисление внутреннего состояния. Однако такие расходы с лихвой компенсируются экономией памяти за счет разделения объектов-приспособленцев, которая получается из-за:
1) уменьшение общего числа экземпляров;
2) сокращение объема памяти, необходимого для хранения внутреннего состояния;
3) вычисление, а не хранение внешнего состояния.
Чем выше степень разделения приспособленцев, тем существеннее экономия.

Реализация
// Приспособленец, объявляет интерфейс, с помощью которого можно 
// получать внешнее состояние или как-то воздействовать на него
class Flyweight {
public:
  virtual char geta() const=0; // символ
  virtual int getb() const=0; // размер
};
// Фабрика приспособленцев создает объекты-приспособленцы и управляет ими
class FlyweightFactory {
  vector<char> a; // уникальное значение для каждого объекта
  map<int, int> b; // значение одинаково для нескольких последовательных объектов
  typedef map<int, Flyweight *> fwmap;
  fwmap fw;
  char geta(int n) { return a[n]; }
  int getb(int n) { return (--b.upper_bound(n))->second; }
  void release(int n) { fw.erase(n); }
  friend class ConcreteFlyweight;
  friend class UnsharedFlyweight;
public:
  Flyweight *getFlyweight(int n);
};
// Конкретный приспособленец, хранит состояние внутри
class ConcreteFlyweight {
  char a;
  int b;
  FlyweightFactory *f;
  int n;
  ConcreteFlyweight(FlyweightFactory *f, int n):f(f),n(n) 
  { a=f->geta(n); b=f->getb(n); }
  friend class FlyweightFactory;
public:
  ~ConcreteFlyweight() { f->release(n); }
  char geta() const { return a; }
  int getb() const { return b; }
};
// Неразделяемый конкретный приспособленец
class UnsharedFlyweight {
  FlyweightFactory *f;
  int n;
  UnsharedFlyweight(FlyweightFactory *f, int n):f(f),n(n) {}
  friend class FlyweightFactory;
public:
  ~UnsharedFlyweight() { f->release(n); }
  char geta() const { return f->geta(n); }
  int getb() const { return f->getb(n); }
};
Flyweight *FlyweightFactory::getFlyweight(int n);
{ fwmap::iterator f=fw.find(n);
  if(f!=fw.end())
    return f->second;
  return fw[n]=new ConcreteFlyweight(this,n);
}
Этот вариант можно использовать, когда не будет удаления и добавления элементов в набор. В случае частых добавлений и удалений для повышения эффективности для хранения состояний элементов набора вместо vector и map нужно использовать специальные структуры данных (дерево интервалов, `√`-декомпозицию).
loading