Introducció al Patró Flyweight

El patró Flyweight és un patró estructural que té com a objectiu reduir la quantitat de memòria utilitzada per un programa quan es treballa amb un gran nombre d'objectes similars. Aquest patró aconsegueix això compartint parts comunes dels objectes en lloc de mantenir còpies separades per a cada objecte.

Conceptes Clau

  • Compartició: El Flyweight permet compartir objectes per reduir l'ús de memòria.
  • Estat Intrínsec: Part de l'estat que és compartida entre tots els objectes Flyweight.
  • Estat Extrínsec: Part de l'estat que és específica per a cada objecte i no es comparteix.

Estructura del Patró Flyweight

El patró Flyweight es compon de les següents parts:

  1. Flyweight: Interfície que defineix les operacions que poden ser realitzades per l'objecte Flyweight.
  2. ConcreteFlyweight: Implementació concreta de l'objecte Flyweight que comparteix l'estat intrínsec.
  3. FlyweightFactory: Crea i gestiona objectes Flyweight. Assegura que els objectes Flyweight es comparteixin correctament.
  4. Client: Utilitza els objectes Flyweight i gestiona l'estat extrínsec.

Diagrama UML

+-------------------+          +-------------------+
|   Flyweight       |<---------|   FlyweightFactory|
+-------------------+          +-------------------+
| +operation()      |          | +getFlyweight()   |
+-------------------+          +-------------------+
           ^
           |
           |
+-------------------+
|ConcreteFlyweight  |
+-------------------+
| +operation()      |
+-------------------+

Implementació en Codi

Exemple en Java

// Flyweight Interface
interface Flyweight {
    void operation(String extrinsicState);
}

// ConcreteFlyweight
class ConcreteFlyweight implements Flyweight {
    private final String intrinsicState;

    public ConcreteFlyweight(String intrinsicState) {
        this.intrinsicState = intrinsicState;
    }

    @Override
    public void operation(String extrinsicState) {
        System.out.println("Intrinsic State: " + intrinsicState + ", Extrinsic State: " + extrinsicState);
    }
}

// FlyweightFactory
class FlyweightFactory {
    private final Map<String, Flyweight> flyweights = new HashMap<>();

    public Flyweight getFlyweight(String key) {
        if (!flyweights.containsKey(key)) {
            flyweights.put(key, new ConcreteFlyweight(key));
        }
        return flyweights.get(key);
    }
}

// Client
public class FlyweightPatternDemo {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();

        Flyweight flyweight1 = factory.getFlyweight("A");
        flyweight1.operation("First Call");

        Flyweight flyweight2 = factory.getFlyweight("B");
        flyweight2.operation("Second Call");

        Flyweight flyweight3 = factory.getFlyweight("A");
        flyweight3.operation("Third Call");
    }
}

Explicació del Codi

  1. Flyweight Interface: Defineix l'operació operation que accepta l'estat extrínsec com a paràmetre.
  2. ConcreteFlyweight: Implementa la interfície Flyweight i manté l'estat intrínsec.
  3. FlyweightFactory: Gestiona la creació i compartició dels objectes Flyweight. Utilitza un Map per emmagatzemar i recuperar els objectes Flyweight.
  4. Client: Utilitza la fàbrica per obtenir objectes Flyweight i invoca les operacions amb l'estat extrínsec.

Exercici Pràctic

Enunciat

Implementa el patró Flyweight per gestionar un sistema de caràcters en un editor de text. Cada caràcter ha de ser un objecte Flyweight que comparteix l'estat intrínsec (el caràcter en si) i té un estat extrínsec (la posició en el text).

Solució

// Flyweight Interface
interface CharacterFlyweight {
    void display(int position);
}

// ConcreteFlyweight
class ConcreteCharacterFlyweight implements CharacterFlyweight {
    private final char intrinsicState;

    public ConcreteCharacterFlyweight(char intrinsicState) {
        this.intrinsicState = intrinsicState;
    }

    @Override
    public void display(int position) {
        System.out.println("Character: " + intrinsicState + ", Position: " + position);
    }
}

// FlyweightFactory
class CharacterFlyweightFactory {
    private final Map<Character, CharacterFlyweight> flyweights = new HashMap<>();

    public CharacterFlyweight getFlyweight(char key) {
        if (!flyweights.containsKey(key)) {
            flyweights.put(key, new ConcreteCharacterFlyweight(key));
        }
        return flyweights.get(key);
    }
}

// Client
public class FlyweightPatternTextEditor {
    public static void main(String[] args) {
        CharacterFlyweightFactory factory = new CharacterFlyweightFactory();

        String text = "HELLO FLYWEIGHT";
        for (int i = 0; i < text.length(); i++) {
            CharacterFlyweight flyweight = factory.getFlyweight(text.charAt(i));
            flyweight.display(i);
        }
    }
}

Explicació de la Solució

  1. CharacterFlyweight Interface: Defineix l'operació display que accepta la posició com a paràmetre.
  2. ConcreteCharacterFlyweight: Implementa la interfície CharacterFlyweight i manté l'estat intrínsec (el caràcter).
  3. CharacterFlyweightFactory: Gestiona la creació i compartició dels objectes CharacterFlyweight. Utilitza un Map per emmagatzemar i recuperar els objectes CharacterFlyweight.
  4. Client: Utilitza la fàbrica per obtenir objectes CharacterFlyweight i invoca les operacions amb la posició del caràcter en el text.

Resum

El patró Flyweight és útil per optimitzar l'ús de memòria en aplicacions que treballen amb un gran nombre d'objectes similars. Compartint l'estat intrínsec i gestionant l'estat extrínsec, aquest patró permet reduir significativament la quantitat de memòria necessària. Hem vist la seva implementació en Java i hem practicat amb un exemple d'un editor de text.

© Copyright 2024. Tots els drets reservats