tl  tr
  Home | Tutorials | Articles | Videos | Products | Tools | Search
Interviews | Open Source | Tag Cloud | Follow Us | Bookmark | Contact   
 Design Patterns > Java Design Patterns > Flyweight

Flyweight 

Flyweight comes under Structural design pattern. It minimizes the memory usage be sharing common resources with other similar objects.

Behaviour & Advantages

  • Supports large number of objects by efficiently sharing common features.
  • Minimizes the Memory footprint of a program.
Participants
  • Flyweight
    Defines an abstract interface through which flyweight can receive and act on extrinsic state.
  • Concrete Flyweight
    An implementation of Flyweight interface which acts as common sharable resource or feature. It must maintains an intrinsic state which is independent of the ConcreteFlyweight object's context.
  • Flyweight Factory
    It creates and manages flyweight objects. When a client requests a flyweight, it returns one from the pool if it is available otherwise creates a new flyweight instance, updates the pool with new instance and returns the flyweight.
  • Client
    One who uses Flyweight through Flyweight Factory.

This example shows Label character border Flyweight Factory which returns character border Flyweight instances as needed. Internally it maintains a map of border character and border instance. Even though we have rendered six borders around different labels it has just created two border instances.

Label class is shown below,

File Name  :  
com/bethecoder/tutorials/dp/fly_weight/Label.java 
   
package com.bethecoder.tutorials.dp.fly_weight;

public class Label {

  private String text;
  private ICharBorder charBoarder;
  
  public Label(String text, ICharBorder charBoarder) {
    super();
    this.text = text;
    this.charBoarder = charBoarder;
  }
  
  public String getText() {
    return text;
  }

  public void setText(String text) {
    this.text = text;
  }
  
  public void print() {
    charBoarder.render(this);
  }
}
   

CharBorder Flyweight.

File Name  :  
com/bethecoder/tutorials/dp/fly_weight/ICharBorder.java 
   
package com.bethecoder.tutorials.dp.fly_weight;

public interface ICharBorder {
  /**
   * Render boarder around user given label. 
   */
  public void render(Label label);
}
   

SimpleCharBorder Concrete Flyweight.

File Name  :  
com/bethecoder/tutorials/dp/fly_weight/SimpleCharBorder.java 
   
package com.bethecoder.tutorials.dp.fly_weight;

import java.util.Arrays;

public class SimpleCharBorder implements ICharBorder {

  private char borderChar = ' ';
  
  public SimpleCharBorder(char borderChar) {
    this.borderChar = borderChar;
  }
  
  @Override
  public void render(Label label) {

    char [] border = new char[label.getText().length() 4];
    Arrays.fill(border, borderChar);
    
    System.out.println(String.valueOf(border));
    System.out.println(borderChar + " " + label.getText() " " + borderChar);
    System.out.println(String.valueOf(border));
  }

}
   

Character border flyweight factory.

File Name  :  
com/bethecoder/tutorials/dp/fly_weight/BorderFactory.java 
   
package com.bethecoder.tutorials.dp.fly_weight;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BorderFactory {

  private static Map<Character, ICharBorder> borderMap =
     new HashMap<Character, ICharBorder>();
  
  private static BorderFactory instance = null;
  
  private BorderFactory() {
  }
  
  public static BorderFactory getInstance() {
    if (instance == null) {
      instance = new BorderFactory();
    }
    return instance;
  }
  
  public synchronized ICharBorder getBoarder(char borderChar) {
    
    ICharBorder border = null;
    
    if (borderMap.containsKey(borderChar)) {
      border =  borderMap.get(borderChar);
    else {
      border = new SimpleCharBorder(borderChar);
      borderMap.put(borderChar, border);
    }
    
    return border;
  }
  
  public List<ICharBorder> getAvailableBordersAsOfNow() {
    return new ArrayList<ICharBorder>(borderMap.values());
  }
}
   

Flyweight usage is shown below,

File Name  :  
com/bethecoder/tutorials/dp/fly_weight/Test.java 
   
package com.bethecoder.tutorials.dp.fly_weight;

public class Test {

  /**
   @param args
   */
  public static void main(String[] args) {

    Label label = new Label("BE THE CODER", BorderFactory.getInstance().getBoarder('/'));
    label.print();
    
    label = new Label("ABC", BorderFactory.getInstance().getBoarder('/'));
    label.print();
    
    label = new Label("DEF", BorderFactory.getInstance().getBoarder('/'));
    label.print();
    
    label = new Label("PQR", BorderFactory.getInstance().getBoarder('#'));
    label.print();
    
    label = new Label("MNO", BorderFactory.getInstance().getBoarder('#'));
    label.print();
    
    label = new Label("XYZ", BorderFactory.getInstance().getBoarder('#'));
    label.print();
    
    System.out.println("Borders instantiated : " 
        BorderFactory.getInstance().getAvailableBordersAsOfNow().size());
  }

}
   

It gives the following output,
////////////////
/ BE THE CODER /
////////////////
///////
/ ABC /
///////
///////
/ DEF /
///////
#######
# PQR #
#######
#######
# MNO #
#######
#######
# XYZ #
#######
Borders instantiated : 2



 
  


  
bl  br