Wednesday, January 5, 2011

Flyweight : Design Pattern

- Flyweight design pattern
   1. Identify shareable state (intrinsic) and non-shareable state (extrinsic)
   2. Create a Factory that can return an existing object or a new object f(containing sharable state)
   3. The client must use the Factory instead of “new” to request objects
   4. The client (or a third party) must provide/compute the extrinsic state
  




 






- Basically in simple language. Keep classes with sharable state as a factory. Whenever a client request for a state, give it back the same instance of the state. If you have three different states, always keep giving back those 3 refrences to states based on input state type.   i.e  if all of the objects share some intrinsic, invariant information that is constant among all of them, it can be removed from each object, and referenced. 

Above eliminates the redundancy of having to repeat the same invariant, intrinsic information for each object, so instead of storing the same information n times for n objects, it is only stored once. This object that contains all of the intrinsic information is called a flyweight object.

- It is possible for a flyweight to have extrinsic information as well. This information must be stateless and determined by context, having no stored values, but values that can be calculated on the spot. This separation into extrinsic and intrinsic information allows great numbers of similar objects to exist, differing only in the context in which they exist.

- The different components involved in the Flyweight Pattern are the Flyweight, the ConcreteFlyweight, the FlyweightFactory and the Client.

The Flyweight itself is the set of intrinsic information that a set of objects share in common. It is abstract.

The ConcreteFlyweight is a subclass of the Flyweight, and contains all of its information, as well as how to calculate extrinsic information for a particular (yet arbitrary) object. It is shared among more than one object.

The FlyweightFactory serves to dispense particular flyweights requested. When a Flyweight with certain properties is requested, it checks to see if one already exists, and if so, returns that flyweight. If the requested flyweight does not exist, it creates the requisite flyweight, stores it, and then returns it.

The Client, in creating a new object, must assign a flyweight to it, so it asks the FlyweightFactory for a particular flyweight, receives that flyweight, and creates a reference to it in the object it is creating.


Clients don't directly instantiate flyweights; instead they get them from a factory. The factory first checks to see if it has a flyweight that fits specific criteria (e.g., a blue or white line); if so, the factory returns a reference to the flyweight. If the factory can't locate a flyweight for the specified criteria, it instantiates one, adds it to the pool, and returns it to the client.


To decide if some part of your program is a candidate for using Flyweights, consider whether it is possible to remove some data from the class and make it extrinsic. If this makes it possible to reduce greatly the number of different class instances your program needs to maintain, this might be a case where Flyweights will help.


public abstract class Flyweight {
public abstract void printState();
}



public class ConcreteFlyWeight extends Flyweight {
//This flyweight stores state
String state ;

public ConcreteFlyWeight(String val) {
this.state = val;
}
public void printState() {
System.out.print(", STATE: " + state);
}


public String getState() {
return state;
}
}



public class FactoryFlyWeight {
  ConcreteFlyWeight weights[] = new ConcreteFlyWeight[2];

int count = 0;

public ConcreteFlyWeight getFlyweight(String argState) {
       if (count > 0) {
          for (int i = 0; i < count; i++) {
              if (argState.equals(weights[i].getState())) {
                  return weights[i];
              }
          }
      }
      weights[count] = new ConcreteFlyWeight(argState);
      return weights[count++];
  }
public int getStateCount() {
return count;
}
}


public class OrderNo {   //extrinsic function
private int orderNo = 0;

public OrderNo(int val) {
this.orderNo = val;
}

public int getOrderNo() {
return this.orderNo;
}

}



public class Client {
static ConcreteFlyWeight [] concreteFly = new ConcreteFlyWeight[100];
static OrderNo [] orders = new OrderNo[100];
static int inputCount = 0;
static FactoryFlyWeight factory;

public static void takeOrder(String arg, int orderNo) {
concreteFly[inputCount] = factory.getFlyweight(arg);
orders[inputCount] = new OrderNo(orderNo);
inputCount++;
}

public static void main( String [] args) {
factory = new FactoryFlyWeight();
takeOrder("RED", 1);
takeOrder("BLUE", 1);
takeOrder("BLUE", 2);
takeOrder("RED", 3);

  for (int i = 0; i < inputCount; i++) {
  System.out.println("");
          System.out.print("ORDER NO: " + orders[i].getOrderNo());
  concreteFly[i].printState();
  System.out.println("");
  }  
  
       System.out.println("");
  System.out.println("No of flyweight in action: " +        factory.getStateCount());
}
}


References"
http://www.javaworld.com/javaworld/jw-07-2003/jw-0725-designpatterns.html?page=2
http://www.exciton.cs.rice.edu/javaresources/designpatterns/flyweightpattern.htm
http://sourcemaking.com/design_patterns/flyweight
http://www.fluffycat.com/Java-Design-Patterns/Flyweight/

No comments:

Post a Comment