Friday, 4 April 2014

Flyweight pattern

With the Singleton design pattern, you have only one object of a particular
class throughout your code. With the Flyweight pattern, you might also have
only one object of a particular class — but it looks to your code as though it’s many different objects. A neat trick.

Flyweight pattern is to control object creation and limit the number of objects you need.

This pattern is called flyweight because instead of having to work with many massive, individual objects, you whittle them down to a smaller set of more generic objects, called flyweights that can be configured at runtime to look like the more plentiful, massive objects. Each massive object consumes system resources; by extracting what’s generic from those massive objects and relying on runtime configuration to mimic those massive objects, you save those resources.
Flyweight pattern is primarily used to reduce the number of objects created, to decrease memory footprint and increase performance. This pattern provides ways to decrease objects count thus improving application required objects structure.
Flyweight pattern try to reuse already existing similar kind objects by storing them and creates new object when no matching object is found.
The object which we are going to create in high number should be analyzed before going for flyweight. Idea is to create lesser number of objects by reusing the same objects. Create smaller groups of objects and they should be reused by sharing. Closely look at objects properties and they can be segregated as two types intrinsic and extrinsic. Sharing is judged with respect to a context. Lets take the example of editors
For example assume we are working with an application that maps stars from universe. In this application if we are going to create an object for every star then think of it how much memory we will need. 
Consider a simple text editor where we can use only alphabet set A to Z. If we are going to create 100 page document using this editor we may have 200000 (2000 X 100) characters (assuming 2000 characters / page). Without flyweight we will create 200000 objects to have fine grained control. With such fine control, every character can have its own characteristics like color, font, size, etc. How do we apply flyweight here?

Java Code Implementation for Flyweight

public interface MyShape {
      public void draw(Graphics g, int x, int y, int width, int height,
                  Color color, boolean fill, String font);
}



public class MyOval implements MyShape {

      public void draw(Graphics oval, int x, int y, int width, int height,
                  Color color, boolean fill, String font) {
            oval.setColor(color);
            oval.drawOval(x, y, width, height);
            if (fill)
                  oval.fillOval(x, y, width, height);
      }
}




public class MyRectangle implements MyShape {

      public void draw(Graphics rectangle, int x, int y, int width, int height,
                  Color color, boolean fill, String font) {
            rectangle.setColor(color);
            rectangle.drawRect(x, y, width, height);
            if (fill)
                  rectangle.fillRect(x, y, width, height);
      }
}


public class ShapeFactory {
     
      // same as in singleton design pattern
      private static final HashMap map = new HashMap();

      public static MyShape getShape(String label) {
            MyShape concreteShape = (MyShape) map.get(label);
    //same as in Factory design pattern
            if (concreteShape == null) {
                  if (label.equals("R")) {
                        concreteShape = new MyRectangle();
                  } else if (label.equals("O")) {
                        concreteShape = new MyOval();
                  }
                  map.put(label, concreteShape);
            }
            return concreteShape;
      }
}



import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Client extends JFrame {

      private static final int WIDTH = 400;
      private static final int HEIGHT = 400;

      private static final String shapes[] = { "R", "O" };
      private static final Color colors[] = { Color.red, Color.green, Color.blue };
      private static final boolean fill[] = { true, false };

      public Client() {
            Container contentPane = getContentPane();

            JButton startButton = new JButton("Draw Shapes");
            final JPanel panel = new JPanel();

            contentPane.add(panel, BorderLayout.CENTER);
            contentPane.add(startButton, BorderLayout.SOUTH);
            setSize(400, 400);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setVisible(true);

            startButton.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent event) {
                        Graphics g = panel.getGraphics();
                        for (int i = 0; i < 100; ++i) {
                              MyShape shape = ShapeFactory.getShape(getRandomShape());
                              shape.draw(g, getRandomX(), getRandomY(), getRandomWidth(),
                                          getRandomHeight(), getRandomColor(),
                                          getRandomFill(), "");
                        }
                  }
            });
      }

      private String getRandomShape() {
            return shapes[(int) (Math.random() * shapes.length)];
      }

      private int getRandomX() {
            return (int) (Math.random() * WIDTH);
      }

      private int getRandomY() {
            return (int) (Math.random() * HEIGHT);
      }

      private int getRandomWidth() {
            return (int) (Math.random() * (WIDTH / 7));
      }

      private int getRandomHeight() {
            return (int) (Math.random() * (HEIGHT / 7));
      }

      private Color getRandomColor() {
            return colors[(int) (Math.random() * colors.length)];
      }

      private boolean getRandomFill() {
            return fill[(int) (Math.random() * fill.length)];
      }



      public static void main(String[] args) {
            Client client = new Client();
      }
}

1 comment:

  1. simple example is commiting 100 STUDENT records in DB in a loop

    ReplyDelete