**Հարմարեցնող** (անգլ.՝ Flyweight), կառուցվածքային նախագծման ձևանմուշ, որի դեպքում իրեն որպես ունիկալ ներկայացնող օբյեկտը փաստացի այդպիսին չի հանդիսանում։

Ընդհանուր հասկացողություններ
----------------------------

* Client - հայցող
* Instance - նմուշ
* Implementation - իրականացում
* Product - արգասիք

Նպատակ
------

Օպտիմիզացնում է հիշողության հետ աշխատանքը՝ թույլ չտալով ստեղծել էլեմենտների նմուշներ, որոնք ունեն ընդհանուր հատկություններ։

Նկարագրություն
--------------

Հարմարեցնող ձևանմուշն օգտագործվում է բազմաթիվ փոքր օբյեկտների հետ կապված ռեսուրսների նվազման համար։ Այս ձևանմուշը նախագծելու ժամանակ պետք է առանձնացնել նրա ներքին և արտաքին հատկանիշները։ Ներքին հատկությունները միշտ մնում են անփոփոխ, իսկ արտաքին հատկությունները կարող են կախված լինել կոնտեքստի օգտագործումից և նրանում պետք է իրագործել անհրածեշտ փոփոխություններ։

Հարմարեցնողը լրացնում է Ֆաբրիկային մեթոդ ձևանմուշն այնպես, որ Ֆաբրիկային մեթոդին հայցվորի նոր օբյեկտ ստեղծելու հայցի դեպքում համակարգը սկսում է ման գալ նմանատիպ պարամետրերով օբյեկտ և այն վերադարձնում է հայցողին։ Եթե այդպիսի օբյեկտ համակարգը չի գտնում, ապա ստեղծվում է։

Օրինակներ
---------

### C++

```
#include <map>
#include <iostream>

// "Flyweight"
class Character
{
public:
 virtual ~Character() {}
 virtual void display() const = 0;

protected:
 char mSymbol;
 int mWidth;
 int mHeight;
 int mAscent;
 int mDescent;
 int mPointSize;
};

// "ConcreteFlyweight"
class ConcreteCharacter : public Character
{
public:
 // Constructor
 ConcreteCharacter( char aSymbol, int aPointSize )
 {
 mSymbol = aSymbol;
 mWidth = 120;
 mHeight = 100;
 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( char aKey )
 {
 // Uses "lazy initialization"
 Characters::const\_iterator it = mCharacters.find( aKey );
 if ( mCharacters.end() == it ) {
 const Character\* character = new ConcreteCharacter(aKey, POINT\_SIZE);
 mCharacters[aKey] = character;
 return \*character;
 } else {
 return \*it->second;
 }
 }

 virtual ~CharacterFactory(){
 for (Characters::const\_iterator it = mCharacters.begin(); it != mCharacters.end(); ++it)
 delete it->second;
 }

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

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

 CharacterFactory<12> characterFactory;

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

```

### 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 + ")");
 }
 }
}

```

### Java

```
import java.util.\*;

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);
 effectsSet.addAll(Arrays.asList(effects));
 // 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.
}

```

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * դ
* ք
* խ
Նախագծման ձևանմուշներ |
| --- |
|  |
| ԳօՖիձևանմուշներ | 

|  |  |
| --- | --- |
| Ստեղծող | Աբստրակտ ֆաբրիկա • Կառուցող • Ֆաբրիկային մեթոդ • Նախատիպ • Եզակի օգտագործման |
| Կառուցվածքային | Ադապտեր • Կամուրջ • Կազմող • Դեկորատոր • Ճակատ • Հարմարեցնող • Պրոքսի |
| Վարքագծային | Պարտականությունների շղթա • Հրաման • Թարգմանիչ • Իտերատոր • Միջնորդ • Պահպանող • Դիտորդ • Վիճակ • Մարտավարություն • Կաղապարային մեթոդ • Այցելող |

 |
|  |
| Ստեղծող ձևանմուշներ | Ծույլ բեռնում • Բազմակի օգտագործման • Օբյեկտների ավազան • Ռեսուրսի ստանալը ինիցիալիզացիա է |
|  |
| Կառուցվածքային ձևանմուշներ | Ճակատը հսկող • Մոդուլ |
|  |
| Համաձայնեցման ձևանմուշներ | Ակտիվ օբյեկտ • Հենվող • Մեկուսացում կրկնակի ստուգումով • Ասինքրոն կանչի մեթոդ • Պահպանվող կախոց • Ռեգիստրացնող • Կողպեքավորող • Մոնիտոր • Նախագործող • Ապագործող • Ընթերցողներ-գրողի կողպեք • Պլանավորման • Հոսքերի ավազանի • Հոսքերի լոկալ հիշողություն |
|  |
| Ճարտարապետական ձևանմուշներ | Ճակատը հսկող ձևանմուշ • Զավթող ձևանմուշ • ձևանմուշի ներկայացման վերահսկում • Բազմաշերտ • Հատկորոշում • Հրատարակող-ստորագրող • Մերկ օբյեկտներ • Ծառայության լոկատոր • Ակտիվ գրառման • Բազմության իդենտիֆիկացման • Data access object • Data transfer object |
|  |
| Այլ ձևանմուշներ | Կախվածության ներդնում • Mock օբյեկտ • Զրոյական օբյեկտ • Ծառայող • Թունելային տարատեսակի |

 |