0

We use flyweight when there is need to crate bulk of a particular kind of object. Because they share a common data (intrinsic state) so helps in reducing memory consumption, and also have their own state (extrinsic state) which is not shared among all the other object. Here is a sample code

public abstract class Shape {

    private String color;
    private int x;
    private int y;

    public Shape(String color) {
        super();
        this.color = color;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public abstract String draw();

    @Override
    public String toString() {
        return "[color=" + color + ", x=" + x + ", y=" + y + "]";
    }


}


public class Circle extends Shape {

    public Circle(String color) {
        super(color);
    }

    @Override
    public String draw() {
        // TODO Auto-generated method stub
        return "Circle " + toString();
    }

}

import java.util.HashMap;

public class ShapeFactory {

    private static HashMap<String, Shape> circle_map = new HashMap<>();

    public static Shape getCircle(String size){
        if(!circle_map.containsKey(size))
            circle_map.put(size, new Circle(size));

        return circle_map.get(size);
    }

}

and the driver

public class ShapeDriver {

    public static void main(String[] args) {

        Shape first_circle = ShapeFactory.getCircle("small");
        first_circle.setX(45);
        first_circle.setY(12);
        Shape second_circle = ShapeFactory.getCircle("small");

        System.out.println("First circle" + first_circle);
        System.out.println("Second circle" + second_circle);

        second_circle.setX(62);
        second_circle.setY(23);

        System.out.println("First circle" + first_circle);
        System.out.println("Second circle" + second_circle);
    }

}

In this example i want size to be intrinsic and coordinates(x, y) to be extrinsic but when ever i change the coordinates of first_circle it also reflect the change in second_circle because they are sharing a complete object not just a single state. The output is as follow

First circle[color=small, x=45, y=12]
Second circle[color=small, x=45, y=12]
First circle[color=small, x=62, y=23]
Second circle[color=small, x=62, y=23]

its equivalent to create an object and store it in different objects, but they all have the same state or data then how they have their own data(extrinsic state)?

user464
  • 255
  • 1
  • 2
  • 10
  • Please show the code of your ShapeFactory. – Uwe Allner May 04 '16 at 07:49
  • 1
    Are you sure flyweight is appropriate for this? You want to create a lot of 'circle' objects with different state (i.e. coordinates). Flyweight will then only be able to apply to the shared sate (i.e. colour) - you'll still have to have separate 'shape' instances to connect the flyweight object with the mutable state. – sisyphus May 04 '16 at 10:56
  • Thanks @sisyphus i get your point, I was wrong about flyweight. Color is shared state then flyweight should only store `color` and every time a new object of `circle` will be created with the same color object, as @Glenner003 write. – user464 May 04 '16 at 19:24

1 Answers1

2

Flyweight objects should be immutable.

In you example, you could desperate the reused part (color/size, your examples conflict) in a separate class and use that as a flyweight.

Then you would instantiate a new Circle for each location, but reuse the color object.

public class Color {
     String color;
     public (String color) {
         this.color = color;
     }
     ...
}    

public abstract class Shape {

        private Color color;
        private int x;
        private int y;

        public Shape(Color color) {
            super();
            this.color = color;
        }
        ...    
    }


    public class Circle extends Shape {

        public Circle(Color color) {
            super(Color);
        }

         ...    
    }


    public class ShapeFactory {

        private static HashMap<String, Color> color_map = new HashMap<>();

        public static Shape getCircle(String color){
            if(!color_map.containsKey(color))
                color_map .put(color, new Color(color));

            return new Circle(color_map.get(size));
        }

    }
Glenner003
  • 1,450
  • 10
  • 20
  • 1
    Can you reference a source for the statement, "_Flyweight objects should be immutable_"? I agree with you; but I'm curious whether it's something you've read, or just an opinion. – jaco0646 May 04 '16 at 18:17
  • Thanks @Glenner003, now i understand flyweight should only deal with (store) shared object which in our case is `color` and every time is should create new object of `circle` with shared `color` object. I was following [this](http://www.tutorialspoint.com/design_pattern/flyweight_pattern.htm) example, can you take a look at this? I think its wrong then. – user464 May 04 '16 at 19:28
  • @jaco0646 I probably once read it somewhere, but I don't recall where. Wikipedia however does confirm this: https://en.wikipedia.org/wiki/Flyweight_pattern#Immutability_and_equality – Glenner003 May 09 '16 at 09:49
  • @user464 indeed, would the circles would be put in a list and drawn after creating all of them, each circle of a specific color would share the same coordinates. – Glenner003 May 09 '16 at 09:55
  • Thanks @jaco0646 can you take at [this](http://www.tutorialspoint.com/design_pattern/flyweight_pattern.htm) articles i was following, i think they are doing wrong. – user464 May 17 '16 at 20:21
  • @jaco0646 I would go 'usually immutable'. say you have loads of characters in some text, each character references a font object, so some of these will reference the font object representing 'e'. If you want to change your text to have a slightly bigger 'e' you would simply change the size property of the one 'e' font object (so its not immutable). But yes in most cases the shared component in a flyweight is immutable. – andrew pate Feb 17 '18 at 13:55