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

Материал из 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

Личные инструменты

Served in 0.200 secs.