Showing posts with label private constructor. Show all posts
Showing posts with label private constructor. Show all posts

Monday, February 21, 2011

Flyweight Pattern

Flyweight design pattern is a software design pattern used to minimize memory usage by sharing data. It enables use of large number of objects that would typically require a lot of memory.

A common example of the Flyweight pattern is string pooling. Consider the Java programming language. The String data type is immutable. Because it is guaranteed that the string can never be changed the strings are pooled to ensure that only one instance exists in memory at any given time.

So if you create two strings s1 and s2 which both point to "foo" you really have two pointers to the same location in memory.

Java also employs the Flyweight pattern for Integer object. new Integer(0) actually returns a pointer to pre-constructed object. So if you create one-thousand Objects which each contain an Object of type Integer you will only have one Integer(0) which is an excellent way to save memory.

Structure Summary
  1. Choose a class from which so many instances will be created that performance will suffer.
  2. Identify the state associated with the class that will not vary from one instance to another,and the state that is peculiar to each individual instance.
  3. State that is peculiar i.e cannot be shared will be maintained and supplied by client.
  4. Hundreds of objects can now be exercised by caching and reusing a few "flyweight" objects.
Types of states in FlyWeight object
Flyweight pattern describes how to share objects to allow their use at fine granularities without prohibitive cost.Each "Flyweight" object is divided into 2 pieces.
The state dependent(extrensic) part and the state-independent(intrinsic) part.

Intrinsic state is stored(shared) in the Flyweight object.
Extrensic state is stored or computed by client objects,and passed to the Flyweight when its operations are invoked.

Flyweights are shared objects and that using them can result in substantial performance gains.
Flyweights are typically instantiated by a flyweight factory that creates a limited number of flyweights and doles them out,one at a time to clients.

For example, you might have a pool of line objects that know how to draw lines. In that case, the flyweight factory could create one line object for each line color, such as one object for white lines and another for blue lines.
Those lines, which are flyweights, get reused whenever you draw white or blue lines.
If you have a drawing with 1,000 white lines and 6,000 blue lines, only two lines—instead of 7,000—are actually instantiated.

In java strings specified at compile-time are flyweights—strings that contain the same character sequence are shared. That sharing can greatly reduce memory footprints, and therefore, increase performance. Strings computed at runtime, are not flyweights by default; however, you can force the issue with the String.intern() which returns flyweights for strings computed at runtime.


While your writing your programs consider if you could use the Flyweight pattern to save memory. An example I used was for a Object that contained three Strings. This tuple uniquely identified a configuration of runs that were stored in the database. The Strings were loaded via JDBC so they didn't get the String pooling provided by Java. Instead I made the constructor to the class private and exposed a public static method called 'get'. This method took the three strings and created the object if not already existing and returned a pointer. This cut my memory usage drastically.

Implementation

flyweight-design-pattern-uml

This UML diagram shows that, Flyweights are typically instantiated by a flyweight factory that creates a limited number of flyweights and sends them out, one at a time to its clients.


Clients don’t instantiate flyweights directly; instead they get them from a Flyweight Factory. The factory first checks to see if it has a flyweight that fits specific criteria; 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.

Flyweight declares an interface through which flyweights can receive and act on extrinsic state. ConcreteFlyweight implements the Flyweight interface and adds storage for intrinsic state, if any in order to share an object. FlyweightFactory creates and manages flyweight objects. We can understand the flyweight pattern better using a simple example. Suppose, you want to show a file system with folders to show the directories or subdirectories, then you don’t need to load all the files or directories at one loading time. You may show the upper level folders first. If the user clicks a folder, then load its subdirectories and files. The shared trigger is mouse-clicked. The composite pattern may be combined to define the flyweight system.

Example
Here is an example of my use of the Flyweight pattern.
IFlyWeight.java -  the interface

interface IFlyWeight {
  public String getName();
  public String getAddress();
}

The IFlyWeight is an interface thatreturns the name and address of theemployees based on their specific criteria“division”.

FlyweightClient.java
public class FlyweightClient {
  public static void main(String[] args)
         throws Exception {
    Vector empList = store();
    FlyweightFactory factory =
    FlyweightFactory.getInstance();
    for (int i = 0; i < empList.size(); i++) {
      StringTokenizer st = new StringTokenizer();
      String division = st.nextToken();
      IFlyWeight flyweight =
      factory.getFlyweight(division);
      // associate the flyweight
      // with the extrinsic data object.
      VCard card = new VCard(name, flyweight);
      card.print();
    }
  }
  private static Vector store() {
    Vector v = new Vector();
    v.add(“North”);
    v.add(“South”);
    v.add(“North”);
    return v;
  }
}

FlyweightFactory.java
class FlyweightFactory {
  private HashMap lstFlyweight;
  private static FlyweightFactory factory = new
  FlyweightFactory();
    private FlyweightFactory() {
    lstFlyweight = new HashMap();
  }
  public synchronized IFlyweight getFlyweight(String divisionName) {
    if (lstFlyweight.get(divisionName) == null) {
      IFlyWeight fw = new
      Flyweight(divisionName);
      lstFlyweight.put(divisionName, fw);
      return fw;
    } else {
      return
    (IFlyWeight)lstFlyweight.get(divisionName);
    }
  }
  public static FlyweightFactory getInstance() {
    return factory;
  }
Note that FlyWeightFactory class is not yet complete, as we have to add private class called FlyWeight class to it.
The client accesses this factory of employees. Every time, the client wants the information, which is accessed through this Factory class. The specifications are passed through the method parameters and new employee information is returned.

Flyweight class(continued in FlyWeightFactory)
//Inner flyweight class
private class Flyweight 
           implements IFlyweight {
  private String name;
  private String addr;
  private void setValues(String name, String addr) {
    this.name = name;
    this.addr = addr;
  }
  private Flyweight(String division) {
    if (division.equals(“North”)) {
      setValues(“soniya”, “addr1”);
    }
     if (division.equals(“South”)) {
       setValues(“rahul”, “addr2”);
    }
    if (division.equals(“East”)) {
      setValues(“Aqil”, “addr3”);
    }
  }
  public String getName() {
    return company;
  }
  public String getAddress() {
    return address;
  }
}// end of Flyweight
}// end of FlyweightFactory
class VCard {
  String name;
  String title;
  IFlyweight objFW;
  public VCard(String n, IFlyWeight fw) {
    name = n;
    objFW = fw;
  }
  public void print() {
    System.out.println(name);
    System.out.println(name objFW.getAddress());
  }
}



When to use Flightweight Pattern?
  • Use the Flightweight Pattern when one instance of a class can be used to provide many virtual instances.
  • Flightweight Pattern is used when a class has many instances, and they all can be controlled identically.
  • Application uses a large number of objects.
  • Storage(Memory) Cost is high to replicate this large number of multiple users.
  • Either the objects are immutable or their state can be made external.
  • Relatively few shared objects may replace many groups of objects.
  • Application does not depend on object identity.While the user may think they are getting a unique object, they actually have a reference from the cache.

The flyweight design pattern is not recommended when the objects in the cache change rapidly or unexpectedly.
Benifits of Flightweight Pattern
1. Reduces the number of object instances at runtime saving memory.
2. Centralizes state for many virtual objects into a single location.

Drawbacks of Flightweight Pattern
1. Drawback is that once you implemented it, single logical instances of the class will not be able to behave independently from the other instances.

Related Patterns
Abstract Factory,Singleton and Template Method patterns fall under this category.Flyweight pattern is often combined with the Composite Pattern to implement a logically hierarchical structure in terms of a directed-acyclic graph with shared lead nodes.Flyweight is a strategy in which you keep a pool of objects available and create references into the pool of objects for particular views.It uses the idea of canonical objects.A canonical object is a single representative object that represents all other objects for particular type.
Whereas flyweight shows how to make lots of little objects,Facade shows how to make a single object represent an entire subsystem.[GoF,p138]
Flyweight is often combined with Composite to implement shared leaf nodes.[GoF,p206]
Terminal symbols within Interpreter's abstract syntax tree can be shared with Flyweight. [GoF. p255]
Flyweights explain when and how State objects can be shared.[GoF,p313]

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

Summary
Flyweight pattern is kind of optimization, but adds to the complexity of the code, so it must be checked whether after adding flyweight performance really improved. Remember the quote from Donald Knuth: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil ."Also even java is not providing caching for objects like String, until and unless you use intern() method, because object creation is becoming cheaper and cheaper. So think of it when you really have very very large no. of objects.

Constant interface

Constant interface contains no methods but it consists solely of static final fields, each exporting a constant. Classes using these constants implement the interface to avoid the need to qualify constant names with a class name. Here is an example:

// Constant interface pattern - do not use!
public interface PhysicalConstants {
// Avogadro's number (1/mol)
static final double PLANCK_CONSTANT = 6.62e-34;
// Boltzmann constant (J/K)
static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
// Mass of the electron (kg)
static final double ELECTRON_MASS = 9.10938188e-31;
}

The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class's exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them.


Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.There are several constant interfaces in the java platform libraries, such as java.io.ObjectStreamConstants. These interfaces should be regarded as anomalies and should not be emulated.


If you want to export constants, there are several reasonable choices. If the constants are strongly tied to an existing class or interface, you should add them to the class or interface. For example, all of the numerical wrapper classes in the Java platform libraries, such as Integer and Float, export MIN_VALUE and MAX_VALUE constants. If the constants are best viewed as members of an enumerated type, you should export them with a typesafe enum class. Otherwise, you should export the constants with a noninstantiable utility class. Here is a utility class version of the PhysicalConstants example above:

// Constant utility class
public class PhysicalConstants {
private PhysicalConstants() { } // Prevents instantiation
public static final double PLANCK_CONSTANT = 6.622e-34;
public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
public static final double ELECTRON_MASS = 9.10938188e-31;
}

So we make constructor private and fields static.


While the utility class version of PhysicalConstants does require clients to qualify constant
names with a class name, this is a small price to pay for sensible APIs. It is possible that the
language may eventually allow the importation of static fields. In the meantime, you can
minimize the need for excessive typing by storing frequently used constants in local variables
or private static fields, for example:

private static final double PI = Math.PI;
In summary, interfaces should be used only to define types. They should not be used to export constants.

Chitika