Приспособленец (шаблон проектирования)
Материал из Seo Wiki - Поисковая Оптимизация и Программирование
Шаблон Flyweight (Приспособленец) используется для уменьшения затрат при работе с большим количеством мелких объектов.
Содержание |
[править] Цель
Уменьшение количества объектов структуры, имеющих общую сущность, путем использования сущности одного экземпляра.
[править] Описание
[править] Примеры
[править] Пример на 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; }
| структурные шаблоны проектирования |
|
адаптер | мост | компоновщик | декоратор | фасад | заместитель | приспособленец | Выделение частного класса данных |
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