Tuesday, July 3, 2012

Design Patterns in JAVA

1. Flyweight Design Pattern 

Discussion


The Flyweight pattern describes how to share objects to allow their use at fine granularities without prohibitive cost. Each “flyweight” object is divided into two pieces: the state-dependent (extrinsic) part, and the state-independent (intrinsic) part. Intrinsic state is stored (shared) in the Flyweight object. Extrinsic state is stored or computed by client objects, and passed to the Flyweight when its operations are invoked.
/**
 * Interface Flyweight to provide extrinsic operations for the client.
 */
package com.flyweight;

public interface Flyweight {

    void doMath(int a, int b);
}
------------
/**
 * Class implement Flyweight to provide add operation.
 */
package com.flyweight;

public class FlyweightAdder implements Flyweight {

    String operation;

    public FlyweightAdder() {
        operation = "adding";
        try {
            System.out.println(operation);
            System.out.println(System.currentTimeMillis());
            Thread.sleep(3000);
            System.out.println(System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.flyweight.Flyweight#doMath(int, int)
     */
    @Override
    public void doMath(int a, int b) {
        System.out.println(operation + " " + a + " and " + b + ": " + (a + b));
    }

}
------------------
/**
 * Class implement Flyweight to provide subtract operation.
 */
package com.flyweight;

public class FlyweightSubtractor implements Flyweight {

    String operation;

    public FlyweightSubtractor() {
        operation = "subtracting";
        try {
            System.out.println(operation);
            System.out.println(System.currentTimeMillis());
            Thread.sleep(3000);
            System.out.println(System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.flyweight.Flyweight#doMath(int, int)
     */
    @Override
    public void doMath(int a, int b) {
        System.out.println(operation + " " + a + " and " + b + ": " + (a - b));
    }

}
---------------------
/**
 * Class FlyweightFactory is a singleton pattern contains Flyweight pool. 
 * picks requested Flyweight instance from pool and provides operations by client.   
 */
package com.flyweight;

import java.util.HashMap;
import java.util.Map;

public class FlyweightFactory {

    private static FlyweightFactory flyweightFactory;

    private Map flyweightPool;

    private FlyweightFactory() {
        flyweightPool = new HashMap();
    }

    public static FlyweightFactory getInstance() {
        if (flyweightFactory == null) {
            flyweightFactory = new FlyweightFactory();
        }
        return flyweightFactory;
    }

    public Flyweight getFlyweight(String key) {
        if (flyweightPool.containsKey(key)) {
            return flyweightPool.get(key);
        } else {
            Flyweight flyweight;
            if ("add".equals(key)) {
                flyweight = new FlyweightAdder();
            } else {
                flyweight = new FlyweightSubtractor();
            }
            flyweightPool.put(key, flyweight);
            return flyweight;
        }
    }

}
-------------------
/**
 *Code Snippet to get flyweight object from pool 
 */
package com.flyweight;

public class FlyweightDemo {

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

        FlyweightFactory flyweightFactory = FlyweightFactory.getInstance();

        for (int f = 1; f < 6; f++) {
            Flyweight flyweightAdder = flyweightFactory.getFlyweight("add");
            flyweightAdder.doMath(f, f);

            Flyweight flyweightSubtractor = flyweightFactory.getFlyweight("subtract");
            flyweightSubtractor.doMath(f, f);
        }
    }
}
----------

Check list

  1. Ensure that object overhead is an issue needing attention, and, the client of the class is able and willing to absorb responsibility realignment.
  2. Divide the target class’s state into: shareable (intrinsic) state, and non-shareable (extrinsic) state.
  3. Remove the non-shareable state from the class attributes, and add it the calling argument list of affected methods.
  4. Create a Factory that can cache and reuse existing class instances.
  5. The client must use the Factory instead of the new operator to request objects.
  6. The client (or a third party) must look-up or compute the non-shareable state, and supply that state to class methods.

Rules of thumb


  1. Whereas Flyweight shows how to make lots of little objects, Facade shows how to make a single object represent an entire subsystem.
  2. Flyweight is often combined with Composite to implement shared leaf nodes.
  3. Terminal symbols within Interpreter’s abstract syntax tree can be shared with Flyweight.
  4. Flyweight explains when and how State objects can be shared.

No comments: