- Proxy could be used when you want to lazy-instantiate an object, or hide the fact that you're calling a remote service, or control access to the object.
See proxy pattern with details. - Decorator is also called "Smart Proxy." This is used when you want to add functionality to an object, but not by extending that object's type. This allows you to do so at runtime.
- Adapter / Wrapper is used when you have an abstract interface, and you want to map that interface to another object which has similar functional role, but a different interface.
In particular Decorator looks very close to Adapter but still there is basic difference:Adapter / Wrapper Decorator Composes "origin" class True True Modifies original interface True False Modifies behavior of interfaceFalse True Proxies method calls True True - Bridge is very similar to Adapter, but we call it Bridge when you define both the abstract interface and the underlying implementation. I.e. you're not adapting to some legacy or third-party code, you're the designer of all the code but you need to be able to swap out different implementations.
See bridge pattern with example. - Facade is a higher-level (read: simpler) interface to a subsystem of one or more classes. Think of Facade as a sort of container for other objects, as opposed to simply a wrapper. So you don't have to worry about so many things, just call the facade to do all the stuff.
See Facade pattern with example.
Tuesday, 27 September 2011
Difference between Proxy, Decorator, Adaptor, and Bridge Patterns ?
Thursday, 19 May 2011
Structural Patterns
Following are the patterns under this category:
Adapter pattern / Wrapper pattern
FlyWeight Pattern
Bridge Pattern
Composite pattern
Decorator pattern
Proxy Pattern
Bridge Pattern
The Bridge Pattern allows you to vary the implementation and abstraction by placing the two in seperate hierarchies.
Decouple an abstraction or interface from its implementation so that the two can vary independently. It is a structural design pattern.
The bridge uses encapsulation, aggregation, and can use inheritance to separate responsibilities into different classes.
Example
The bridge pattern can be demonstrated with an example. Suppose we have a Vehicle class. We can extract out the implementation of the engine into an Engine class. We can reference this Engine implementor in our Vehicle via an Engine field. We'll declare Vehicle to be an abstract class. Subclasses of Vehicle need to implement the drive() method. Notice that the Engine reference can be changed via the setEngine() method.
Example Code for Bridge Pattern
Consider a class called Vehicle:
public abstract class Vehicle {
//Vehicle have components like engine, tyre
//add other components like headlight, music system etc..
//but I just took 2 for simplicity
Engine engine;
Tyre tyre;
//assembling cose is fixed here, but can be variable
float assemblingCost;
public abstract void drive();
public void setEngine(Engine engine) {
this.engine = engine;
}
public void setTyres(Tyre tyre)
{
this.tyre = tyre;
}
public void assembleVehicle(Engine engine,Tyre tyre)
{
this.engine=engine;
this.tyre = tyre;
}
public float getPrice()
{
return tyre.getCost()+engine.getCost()+assemblingCost;
}
}
public class BigTruck extends Vehicle {
public BigTruck(Engine engine,Tyre tyre) {
this.assemblingCost = 3000;
assembleEngine(engine,tyre);//calls assembleEngine
// from base class
}
@Override
public void drive() {
System.out.println("Driving the truck now, with cost:"+
getPrice();
}
}
public class SmallCar extends Vehicle {
public SmallCar(Engine engine,Tyre tyre) {
this.assemblingCost = 2000;
assembleEngine(engine,tyre);//calls assembleEngine
// from base class
}
@Override
public void drive() {
System.out.println("Driving the car now, with cost:"+
getPrice();engine.kickStart();
tyre.roll();
}
}
Now getting the components of the cars:
Engine of the car:
public interface Engine {
public int kickStart();
}
public class BigEngine implements Engine {
int horsepower;
public BigEngine() {
horsepower = 350;
}
@Override
public int kickStart() {
System.out.println("The big engine is running");
return horsepower;
}
}
public class SmallEngine implements Engine {
int horsepower;
public SmallEngine() {
horsepower = 100;
}
@Override
public int kickStart() {
System.out.println("The small engine is running");
return horsepower;
}
}
public interface Tyre{
public void roll();
}
public class ThickTyre implements Tyre{
private int width;
public ThickTyre(){
width=200;
}
public void roll(){
System.out.println("Rolling on thick tyres of width:"
+ width);
}
}
public class MediumTyre implements Tyre{
private int width;
public MediumTyre (){
width=140;
}
public void roll(){
System.out.println("Rolling on thin tyres of width:"
+ width);
}
}
public class BridgeDemo {
public static void main(String[] args) {
Vehicle vehicle = new BigTruck(new SmallEngine(),new ThickTyre());
vehicle.drive();
vehicle.assembleVehicle(new BigEngine(),new ThickTyre());
vehicle.drive();
vehicle = new SmallCar(new SmallEngine(),new MediumTyre());
vehicle.drive();
vehicle.assembleVehicle(new BigEngine(),new MediumTyre());
vehicle.drive();
}
}
Benefits of Bridge Pattern
Wednesday, 2 March 2011
Proxy Pattern
It means we are representing a complex object with a simpler one.
Motivation
The Need:
- Control access to an object
- Examples:
- The object may be expensive to use (e.g., the manipulation of an image) and it may not be necessary to do so (e.g., because the image is not visible or because you are using a thumbnail)
- The object being accessed may reside on a "remote" address space/machine and special "communications" may be required
- The object being accessed may be "priveleged" (e.g., for security reasons) in some applications and not in others


-> A RemoteProxy manages interaction between a client and a remote object.
-> A Virtual Proxy controls access to an object that is expensive to instantiate.
-> A Protection Proxy controls access to the methods of an object based on the caller.
-> A smart proxy interposes additional actions when an object is accessed. Typical uses include:
1. Counting the number of references to the real object so that it can be freed automatically when there are no more references
2. Loading a persistent object into memory when it's first referenced
3. Checking that the real object is locked before it is accessed to ensure that no other object can change it.
Even many other variants of Proxy Pattern exists.
When to use:
1. Use the proxy Pattern in situations where client does not or can not reference an
object directly, but wants to still interact with the object
2. Use the proxy Pattern to create a representative object that controls access to another object, which may be remote, expensive to create or in need of securing.
-> The proxy object has the same interface as the target object
-> The proxy holds a reference to the target object and can forward requests to
the target as required (delegation!)
-> In effect, the proxy object has the authority the act on behalf of the client to
interact with the target object
To make clients use Proxy rather than the Real One, provide a factory that instantiates and returns the subject. Because this happens in a factory method we can then wrap the real one with a proxy before returning it. The client never knows or cares that it's using a proxy instead of the real thing.
Let us take a real time use of Proxy Pattern as an example.
By the way this code bit is from my Personal Project...
This is an example of static Proxy.
Java's built-in support for Proxy can build a dynamic proxy class on demand and dispatch all calls on it to a handler of your choosing.
Like any wrapper, proxy will increase the number of classes and objects in your designs.
Rules of thumb
1. Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface. [GoF. p216]
2. Decorator and Proxy have different purposes but similar structures. Both describe how to provide a level of indirection to another object, and the implementations keep a reference to the object to which they forward requests. [GoF, p220]
3. Proxy controls access to objects . But Decorator decorates the objects by adding behaviour to them.
Composite Pattern in Java
Composite allows you to compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
Whenever we have a requirement of handling all the objects in the same structure we can go for composite pattern, where we can create a tree structure that contain both composition of objects and individual objects as nodes and treat all of them uniformly by using same operations.
A Composite contains components i.e.(composites(again can contain components) and leaf elements(cannot contain components again)).
Base Component defines an interface for all objects in the composition. The Client uses this base component class to deal with the objects in the composition. It may also provide the default behaviour for adding,removing or accessing child components. But mostly Component is an interface.
Composite: Defines beahviour of components having children and stores the child components. We can add and remove Component instances to this composite dynamically.
Leaf : Defines the behaviour for the elements in the composition. It doesn't have references to other Components
First we need to have a Component Interface.(BaseComponent where even you can give some default implementation also)
//Component
public interface Component {
public void add(Component countryComponent);
public void remove(Component countryComponent);
public Component getChild(int i);
public String getName();
public String getDescription();
public void print();
}
Then we have Leaf implementation, which further does'nt have references to other components.
//Leaf
public class Leaf implements Component{
private String name;
private String description;
public Leaf(String name,String description){
this.name = name;
this.description = description;
}
/* these three methods doesn't make
* sense for Leaf. So we can even make
* the Base Component as abstract Class
* and provide the default implementation
* instead of this approach.
*/
public void add(Component state){
System.out.println("Sorry, leaf can't have components ");
}
public void remove(Component state){
System.out.println("Sorry, leaf can't have components ");
}
public Component getChild(int i){
System.out.println("Sorry, leaf can't have components ");
throw new UnsupportedOperationException();
}
public void print(){
System.out.println("-------------");
System.out.println("Name ="+getName());
System.out.println("Description ="+getDescription());
System.out.println("-------------");
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and finally the Composite Implementation which again can contain child components.
// Composite
public class Composite implements Component{
private String name;
private String description;
// list of State Components
List<Component> components = new ArrayList<Component>();
public Composite(String name, String description){
this.name = name;
this.description = description;
}
public void add(Component state){
components.add(state);
}
public void remove(Component state){
components.remove(state);
}
public Component getChild(int i){
return components.get(i);
}
public void print(){
System.out.println("-------------");
System.out.println("Name ="+getName());
System.out.println("Description ="+getDescription());
System.out.println("-------------");
Iterator<Component> iterator = components.iterator();
while(iterator.hasNext()){
Component component = iterator.next();
component.print();
}
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Test {
public static void main(String[] args) {
Component leaf = new Leaf("leaf","No components futher");
Component composite = new Composite("composite","Again has components");
Component subcomposite = new Composite("subcomposite","Sub Composite again contain components");
Component baseComponent = new Composite("BaseComponent","Includes all other components");
baseComponent.add(leaf);
baseComponent.add(composite);
baseComponent.add(subcomposite);
baseComponent.print();
}
}
A general consideration when implementing this pattern is whether each component should have a reference to its
container (composite). The benefit of such a reference is that it eases the traversal of the tree, but it also decreases your flexibility.
There are many tradeoffs in implementing Composite. You need to balance transperency and safety with your needs.
Hope this explanation helps.
References : Applied Java Patterns by Stephen Stelting and Olav Maassen
Adapter pattern / Wrapper pattern
This pattern is also known as Wrapper pattern.
Example in Real life
British plugs OR Indian plugs are cylindrical and American plugs are recangularish. You can use an adapter in between to fit an American (rectangular) plug in British (cylindrical) socket assuming voltage requirements are met with.
Types of Adapters
There are two kinds of adapters( base on composition vs inheritance).
1. Object Adapters (based on composition )
2. Class Adapters(based on inheritance)
Adapter pattern using composition
Object Adapters : Object Adapters use a compositional technique to adapt one interface to another. The adapter inherits the target interface that the client expects to see, while it holds an instance of adaptee. Object adapters enable the client and the adaptee to be completely decoupled from eachother. Only the adapter knows about both of them.
Before going deeper let us have a simple example.
Consider the scenario where our legacy code that exposes the Enumerator interface, but we want our new code to only use iterators.
Here EnumerationIterator is our Adapter.
As we know Enumerator does not support remove(). There is no way to implement a fully functioning remove() method on the adapter. So let us try to throw RunTimeException. As we know remove() method in Iterator throws Unsupported Operation Exception. As long as client is careful (watchout for potential exceptions) and the adapter is well documented it is perfectly reasonable solution.
/*
* We are Adapting Enumeration to Iterator.
* Adapter EnumeratorIterator implements Iterator to look like an Iterator
*/
public class EnumeratorIterator implements Iterator{
Enumeration enumeration;
public EnumeratorIterator(Enumeration enumeration){
this.enumeration = enumeration;
}
// Iterator's hasNext() method is delegated to Enumerator's hasMoreElements()
public boolean hasNext(){
return enumeration.hasMoreElements();
}
// Iterator's next() method is delegated to Enumerator's nextElement()
public Object next(){
return enumeration.nextElement();
}
public void remove(){
throw new UnsupportedOperationException();
}
}
How can Client use Adapter:
1. The Client makes a request to the adapter by calling a method on it using the target interface.
2. The Adapter translates that request into one or more calls on adaptee using adaptee interface.
3. The client receives the result of the call and never knows there is an adapter doing the translation.
Adapter Pattern using inheritance
Class Adapters : Class adapters use multiple inheritance to achieve their goals. As in the object adapter, the class adapter inherits the interface of the client's target. However, it also inherits the interface of the adaptee as well. Since Java does not support true multiple inheritance, this means that one of the interfaces must be inherited from a Java Interface type. Note that either or both of the target or adaptee interfaces could be an Java Interfaces. The request to the target is simply rerouted to the specific request that was inherited fro the adaptee interface.
Differnce between Object Adapters and Class Adapters
1. As Object Adapter uses composition it can not only adapt an adaptee class, but any of its subclasses. It is flexible.
2. Class Adapter is commited to only one adaptee. But again it has an advantage as no need to implement the entire adaptee. It can just override the behaviour of adaptee and also can override the behaviour as it is subclassing.
3. Note that class adapters have a problem with name conflicts if methods of the same signature exist on both the target and the adaptee. Note that just because two objects have methods that have the same signature (syntax), it does not guarantee that the two methods have the same meaning or behavior (sematics). That is, the two methods do not necessarily map directly to each other. Object adapters do not have this problem.
4. Class adapters are simpler than object adapters in that they involve fewer classes and are useful if total decoupling of the client and adaptee is not needed.
Why should I use Adapter Pattern:
1. Sometimes a toolkit or class library can not be used because its interface is incompatible with the interface required by an application.
2. We can not change the library interface, since we may not have its source code.
3. Even if we did have the source code, we probably should not change the library for each domain-specific application.
4. You don’t want your object models implementing JavaVM specific interfaces becuase they might change in the future.
When to use Adapter Pattern:
Use the Adapter pattern when
1. You want to use an existing class, and its interface does not match the one you need.
2. You want to create a reusable class that cooperates with unrelated classes with incompatible interfaces.
Some of the good OO design principles behind Adapter Pattern:
1. We use object composiition to wrap adaptee with an altered interface. This approach has an added advantage that we can use an adapter with any subclass of adaptee.
2. Pattern binds the client to an interface but not to implementation. We could use several adapters, each converting a different backend set of classes or we could add new implementations after the fact, as long as they adhere to target interface.
Two-way Adapter
A two-way adapter supports both the Target and the Adaptee interface. It allows an adapted object (Adapter) to appear as an Adaptee object or a Target object.
One way to implement two-way adapters is to use multiple inheritance, which can't be done in Java.
But we can have our adapter class implement two different Java interfaces. So the adapter can act as a Old Interface or New Interface.
Comparing Adapter Pattern with other Patterns:
1. Adapter converts one interface to another, Decorator doesn't alter interface but adds responsibility. Facade makes an interface simpler.
Decorator is thus more transparent to the application than an adapter is. As a consequence, Decorator supports recursive composition, which isn't possible with pure Adapters.
2. Adapters allows client to make use of libraries and subsets without changing any code. Decorators allow new behaviour to be added to the classes with out altering the existing code.
3. Adapter make things work after they're designed, Bridge makes them work before they are.
4. Bridge is designed up-front to let the abstraction and the implementation vary independently. Adapter is retrofitted to make unrelated classes work together.
5. Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface.
6. Facade defines a new interface, whereas Adapter reuses an old interface. Remember that Adapter makes two existing interfaces work together as opposed to defining an entirely new one.
Adapter pattern example in java
java.io.InputStreamReader(InputStream)
java.io.OutputStreamWriter(OutputStream)
Sunday, 27 February 2011
Decorator Pattern
A Decorator, also known as a Wrapper, is an object that has an interface identical to an object that it contains. Any calls that the decorator gets, it relays to the object that it contains, and adds its own functionality along the way, either before or after the call. This gives you a lot of flexibility, since you can change what the decorator does at runtime, as opposed to having the change be static and determined at compile time by subclassing. Since a Decorator complies with the interface that the object that it contains, the Decorator is indistinguishable from the object that it contains. That is, a Decorator is a concrete instance of the abstract class, and thus is indistinguishable from any other concrete instance, including other decorators. This can be used to great advantage, as you can recursively nest decorators without any other objects being able to tell the difference, allowing a near infinite amount of customization.
Decorators add the ability to dynamically alter the behavior of an object because a decorator can be added or removed from an object without the client realizing that anything changed. It is a good idea to use a Decorator in a situation where you want to change the behaviour of an object repeatedly (by adding and subtracting functionality) during runtime.
The dynamic behavior modification capability also means that decorators are useful for adapting objects to new situations without re-writing the original object's code.
The code for a decorator would something like this:
void doStuff() {
// any pre-processing code goes here.
aComponent.doStuff() // delegate to the decoree
// any post-processing code goes here
}
Note that the decorator can opt to not delegate to the decoree, if, for instance, some condition was not met.
A very nice example of decorators is Java's I/O stream implementation.
Example
public abstract class Breakfast {
String description = "Unknown Breakfast";
public String getDescription() {
return description;
}
public abstract double cost();
}
Concrete Component
The ConcreteComponent is the object we’re going to dynamically add new behavior to. It extends Component.
public class Dosa extends Breakfast{
public Dosa() {
description = "Dosa";
}
public double cost(){
return 12.50;
}
}
public class Idli extends Breakfast{
public Idli() {
description = "Idli";
}
public double cost(){
return 10.50;
}
}
Each decorator HAS-A (wraps) a component, which means the decorator has an instance variable that holds a reference to a component.
Decorators implement the same interface or abstract class as the component they are going to decorate.
// Decorator
public abstract class Decorator extends Breakfast{
public abstract String getDescription();
}
The ConcreteDecorator has an instance variable for the thing it decorates (the Component the Decorator wraps).
public class MasalaDosaDecorator extends Decorator{
Breakfast breakfast;
public MasalaDosaDecorator(Breakfast breakfast){
this.breakfast = breakfast;
}
public String getDescription(){
return breakfast.getDescription()+" ,its MasalaDosa";
}
public double cost(){
return breakfast.cost() + 5.50;
}
}
public class OnionDosaDecorator extends Decorator{
Breakfast breakfast;
public OnionDosaDecorator(Breakfast breakfast){
this.breakfast = breakfast;
}
public String getDescription(){
return breakfast.getDescription()+" , its OnionDosa";
}
public double cost(){
return breakfast.cost() + 3.50;
}
}
Now its time to have our menu to be served, with main function.
public class BreakfastMenu {
public static void main(String[] args) {
// without adding decorators
Breakfast menu1 = new Dosa();
System.out.println(menu1.getDescription() +" Rs. "+menu1.cost());
//adding decorators
Breakfast menu2 = new MasalaDosaDecorator(new OnionDosaDecorator(new Dosa()));
System.out.println(menu2.getDescription() +" Rs. "+menu2.cost());
Breakfast menu3 = new MasalaDosaDecorator(new Dosa());
System.out.println(menu3.getDescription() +" Rs. "+menu3.cost());
}
}
Decorators can extend the state of the component.
Decorators can add new methods. however new behavior is typically added by doing computation before or after an existing method in the component.
Inheritance is one form of extension, but not necessarily the best way to achieve flexibility in our designs.
In our designs we should allow behavior to be extended without the need to modify existing code.
Composition and delegation can often be used to add new behaviors at runtime.
The Decorator Pattern provides an alternative to subclassing for extending behavior.
The Decorator Pattern involves a set of decorator classes that are used to wrap concrete components.
Decorator classes mirror the type of the components they decorate. (In fact, they are the same type as the components they decorate, either through inheritance or interface implementation.)
Decorators change the behavior of their components by adding new functionality before and/or after (or even in place of) method calls to the component.
You can wrap a component with any number of decorators.
Decorators are typically transparent to the client of the component; that is, unless the client is relying on the component’s concrete type.
Decorators can result in many small objects in our design, and overuse can be complex.
Adapter provides a different interface to its subject.Proxy provides the same interface.Decorator provides an enhanced interface.[GoF, p216]
Adapter changes the object's interface,Decorator enhances an object's responsibilities.Decorator is thus more transparent to the client.As a consequence,Decorator supports recursive composition,which isnt possible with pure Adapters.[GoF, p149]
Composite and Decorator have similar structure diagrams,reflecting the fact that both rely on recursive composition to organize an open-ended number of objects.[GoF, p219]
A Decorator can be viewed as a degenerate Composite with only one component.However a decorator adds additional responsibilities-it isnt intended for object aggregation.[GoF, p184]
Decorator is designed to let you add responsibilites to objects without subclassing.Composite's focus is not an embellishment but on representation.These intents are distinct but complementary.Consequently Composite and Decorator are often used in concert. [GoF, p220]
Decorator lets us change the skin of an object.Strategy lets us change the guts.[GoF, p184]
Decorator and Proxy have diff purposes but similar structures.Both describe how to provide a level of indirection to another object,and the implementations keep a reference to the object to which they forward requests.[GoF, p220]
Disadvantage
Only disadvantage is code maintenance can be a problem as it provides the system with a lot of similar looking small objects(each decorator).
Sunday, 20 February 2011
Flyweight Pattern
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
- Choose a class from which so many instances will be created that performance will suffer.
- 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.
- State that is peculiar i.e cannot be shared will be maintained and supplied by client.
- Hundreds of objects can now be exercised by caching and reusing a few "flyweight" objects.
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

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 {Note that FlyWeightFactory class is not yet complete, as we have to add private class called FlyWeight class to it.
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;
}
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.