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

Материал из Seo Wiki - Поисковая Оптимизация и Программирование
Перейти к навигацииПерейти к поиску

Шаблон Flyweight (Приспособленец) используется для уменьшения затрат при работе с большим количеством мелких объектов.

Цель

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

Описание

Файл:Flyweight.gif

Примеры

Пример на Java

public enum FontEffect {
    BOLD, ITALIC, SUPERSCRIPT, SUBSCRIPT, STRIKETHROUGH
}

public final class FontData {
    /**
     * A weak hash map will drop unused references to FontData.
     * Values have to be wrapped in WeakReferences, 
     * because value objects in weak hash map are held by strong references.
     */
    private static final WeakHashMap<FontData, WeakReference<FontData>> flyweightData =
        new WeakHashMap<FontData, WeakReference<FontData>>();
    private final int pointSize;
    private final String fontFace;
    private final Color color;
    private final Set<FontEffect> effects;

    private FontData(int pointSize, String fontFace, Color color, EnumSet<FontEffect> effects) {
        this.pointSize = pointSize;
        this.fontFace = fontFace;
        this.color = color;
        this.effects = Collections.unmodifiableSet(effects);
    }

    public static FontData create(int pointSize, String fontFace, Color color,
        FontEffect... effects) {
        EnumSet<FontEffect> effectsSet = EnumSet.noneOf(FontEffect.class);
        for (FontEffect fontEffect : effects) {
            effectsSet.add(fontEffect);
        }
        // We are unconcerned with object creation cost, we are reducing overall memory consumption
        FontData data = new FontData(pointSize, fontFace, color, effectsSet);
        if (!flyweightData.containsKey(data)) {
            flyweightData.put(data, new WeakReference<FontData> (data));
        }
        // return the single immutable copy with the given values
        return flyweightData.get(data).get();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof FontData) {
            if (obj == this) {
                return true;
            }
            FontData other = (FontData) obj;
            return other.pointSize == pointSize && other.fontFace.equals(fontFace)
                && other.color.equals(color) && other.effects.equals(effects);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return (pointSize * 37 + effects.hashCode() * 13) * fontFace.hashCode();
    }

    // Getters for the font data, but no setters. FontData is immutable.
}

Пример на C#

using System;
using System.Collections;

namespace Flyweight
{

  class MainApp
  {
    static void Main()
    {
      // Build a document with text
      string document = "AAZZBBZB";
      char[] chars = document.ToCharArray();

      CharacterFactory f = new CharacterFactory();

      // extrinsic state
      int pointSize = 10;

      // For each character use a flyweight object
      foreach (char c in chars)
      {
        pointSize++;
        Character character = f.GetCharacter(c);
        character.Display(pointSize);
      }

      // Wait for user
      Console.Read();
    }
  }

  // "FlyweightFactory"

  class CharacterFactory
  {
    private Hashtable characters = new Hashtable();

    public Character GetCharacter(char key)
    {
      // Uses "lazy initialization"
      Character character = characters[key] as Character;
      if (character == null)
      {
        switch (key)
        {
          case 'A': character = new CharacterA(); break;
          case 'B': character = new CharacterB(); break;
            //...
          case 'Z': character = new CharacterZ(); break;
        }
        characters.Add(key, character);
      }
      return character;
    }
  }

  // "Flyweight"

  abstract class Character
  {
    protected char symbol;
    protected int width;
    protected int height;
    protected int ascent;
    protected int descent;
    protected int pointSize;

    public abstract void Display(int pointSize);
  }

  // "ConcreteFlyweight"

  class CharacterA : Character
  {
    // Constructor
    public CharacterA()
    {
      this.symbol = 'A';
      this.height = 100;
      this.width = 120;
      this.ascent = 70;
      this.descent = 0;
    }

    public override void Display(int pointSize)
    {
      this.pointSize = pointSize;
      Console.WriteLine(this.symbol +
        " (pointsize " + this.pointSize + ")");
    }
  }

  // "ConcreteFlyweight"

  class CharacterB : Character
  {
    // Constructor
    public CharacterB()
    {
      this.symbol = 'B';
      this.height = 100;
      this.width = 140;
      this.ascent = 72;
      this.descent = 0;
    }

    public override void Display(int pointSize)
    {
      this.pointSize = pointSize;
      Console.WriteLine(this.symbol +
        " (pointsize " + this.pointSize + ")");
    }

  }

  // ... C, D, E, etc.

  // "ConcreteFlyweight"

  class CharacterZ : Character
  {
    // Constructor
    public CharacterZ()
    {
      this.symbol = 'Z';
      this.height = 100;
      this.width = 100;
      this.ascent = 68;
      this.descent = 0;
    }

    public override void Display(int pointSize)
    {
      this.pointSize = pointSize;
      Console.WriteLine(this.symbol +
        " (pointsize " + this.pointSize + ")");
    }
  }
}

Пример на C++

#include <map>
#include <iostream>

// "Flyweight"
class Character
	{
	public: 
		virtual void display() const = 0;
	
	protected: 
		char mSymbol;
		int 
			 mWidth
			,mHeight
			,mAscent
			,mDescent
			,mPointSize
			;
	};
 
// "ConcreteFlyweight"
class ConcreteCharacter : public Character
	{
	public: 
		// Constructor
		ConcreteCharacter( const char aSymbol, int aPointSize )
			{
			mSymbol		= aSymbol;
			mHeight		= 100;
			mWidth		= 120;
			mAscent		= 70;
			mDescent	= 0;
			mPointSize	= aPointSize;
			}

		// from Character
		virtual void display() const
			{														  
			std::cout << mSymbol << " ( PointSize " << mPointSize << " )\n";
			}
	};


// "FlyweightFactory"
template< int POINT_SIZE = 10 >
class CharacterFactory
	{

	public: 
		const Character& getCharacter( const char aKey )
			{

			// Uses "lazy initialization"
			Character* character = NULL;
			Characters::iterator it = mCharacters.find( aKey );

			
			if ( mCharacters.end() == it )
				{
				switch (aKey)
					{
					case 'A': character = new ConcreteCharacter('A', POINT_SIZE); break;
					case 'B': character = new ConcreteCharacter('B', POINT_SIZE); break;
					//...
					case 'Z': character = new ConcreteCharacter('Z', POINT_SIZE); break;
					default:  character = new ConcreteCharacter('-', POINT_SIZE); break;
					}
				mCharacters.insert( make_pair( aKey, character ) );
				}
			else
				{
				character = it->second;
				}
			
			return *character;
			}

	private: 
		typedef std::map< char, Character* > Characters;	 
		Characters mCharacters;
	};


int main()
	{
	std::string document = "AAZZBBZB";

	CharacterFactory<12> characterFactory;

	std::string::const_iterator it = document.begin(); 
	while( document.end() != it )
		{
		const Character& character = characterFactory.getCharacter( *it++ );
		character.display();
		}
	return 0;
	}



структурные шаблоны проектирования

адаптер | мост | компоновщик | декоратор | фасад | заместитель | приспособленец | Выделение частного класса данных

bg:Миниобект (шаблон) cs:Flyweight de:Flyweight en:Flyweight pattern es:Flyweight (patrón de diseño) fr:Poids-mouche (patron de conception) it:Flyweight pattern ja:Flyweight パターン ko:플라이웨이트 패턴 pl:Pyłek (wzorzec projektowy) pt:Flyweight uk:Легковаговик (шаблон проектування) vi:Flyweight pattern

Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....