Wednesday, April 11, 2012

Design Patterns





Creational Design Patterns:

Singleton - Ensure that only one instance of a class is created and Provide a global access point to the object.

Factory(Simplified version of Factory Method) - Creates objects without exposing the instantiation logic to the client and Refers to the newly created object through a common interface.

Factory Method - Defines an interface for creating objects, but let subclasses to decide which class to instantiate and Refers to the newly created object through a common interface.

Abstract Factory - Offers the interface for creating a family of related objects, without explicitly specifying their classes.

Builder - Defines an instance for creating an object but letting subclasses decide which class to instantiate and Allows a finer control over the construction process.

Prototype - Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.

Object Pool - reuses and shares objects that are expensive to create..




Behavioral Design Patterns:


Chain of Responsibiliy - It avoids attaching the sender of a request to its receiver, giving this way other objects the possibility of handling the request too. The objects become parts of a chain and the request is sent from one object to another across the chain until one of the objects will handle it.

Command - Encapsulate a request in an object, Allows the parameterization of clients with different requests and Allows saving the requests in a queue.

Interpreter - Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language / Map a domain to a language, the language to a grammar, and the grammar to a hierarchical object-oriented design

Iterator - Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

Mediator - Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

Observer - Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Strategy - Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

Template Method - Define the skeleton of an algorithm in an operation, deferring some steps to subclasses / Template Method lets subclasses redefine certain steps of an algorithm without letting them to change the algorithm's structure.

Visitor - Represents an operation to be performed on the elements of an object structure / Visitor lets you define a new operation without changing the classes of the elements on which it operates.

Null Object - Provide an object as a surrogate for the lack of an object of a given type. / The Null Object Pattern provides intelligent do nothing behavior, hiding the details from its collaborators.




Structural Design Patterns:


Adapter - Convert the interface of a class into another interface clients expect. / Adapter lets classes work together, that could not otherwise because of incompatible interfaces.

Bridge - Compose objects into tree structures to represent part-whole hierarchies. / Composite lets clients treat individual objects and compositions of objects uniformly.

Composite - Compose objects into tree structures to represent part-whole hierarchies. / Composite lets clients treat individual objects and compositions of objects uniformly.

Decorator - add additional responsibilities dynamically to an object.

Flyweight - use sharing to support a large number of objects that have part of their internal state in common where the other part of state can vary.

Memento - capture the internal state of an object without violating encapsulation and thus providing a mean for restoring the object into initial state when needed.

Proxy - provide a “Placeholder” for an object to control references to it.




Design patterns in your Java project

  • Strategy
  • Iterator
  • Decorator
  • Visitor
  • Singleton
  • Factory
  • Command
  • MVC
Strategy pattern

By definition Strategy design pattern  allow an object to change  its behaviour when its internal state changes. The object will appear to change its class. The Strategy design pattern enables a client to choose which algorithm to use from a family of algorithms and gives it a simple way to access it. The algorithms can also be expressed independently of the data they are using.



Strategy - defines an interface common to all supported algorithms. Context uses this interface to call the algorithm defined by a ConcreteStrategy.

ConcreteStrategy - each concrete strategy implements an algorithm.

Context
contains a reference to a strategy object.
may define an interface that lets strategy accessing its data.
The Context objects contains a reference to the ConcreteStrategy that should be used. When an operation is required then the algorithm is run from the strategy object. The Context is not aware of the strategy implementation. If necessary, addition objects can be defined to pass data from context object to strategy.

The context object receives requests from the client and delegates them to the strategy object. Usually the ConcreteStartegy is created by the client and passed to the context. From this point the clients interacts only with the context.

Note:
The strategy design pattern splits the behavior (there are many behaviors) of a class from the class itself. This has some advantages, but the main draw back is that a client must understand how the Strategies differ. Since clients get exposed to implementation issues the strategy design pattern should be used only when the variation in behavior is relevant to them.
Passing data to/from Strategy object

Usually each strategy need data from the context have to return some processed data to the context. This can be achieved in 2 ways.
creating some additional classes to encapsulate the specific data.
passing the context object itself to the strategy objects. The strategy object can set returning data directly in the context.
When data should be passed the drawbacks of each method should be analyzed. For example, if some classes are created to encapsulate additional data, a special care should be paid to what fields are included in the classes. Maybe in the current implementation all required fields are added, but maybe in the future some new strategy concrete classes require data from context which are not include in additional classes. Another fact should be specified at this point: it's very likely that some of the strategy concrete classes will not use field passed to the in the additional classes.

On the other side, if the context object is passed to the strategy then we have a tighter coupling between strategy and context.

Strategy and Bridge Design Pattern
Both of the patterns have the same UML diagram. But they differ in their intent since the strategy is related with the behavior and bridge is for structure. Further more, the coupling between the context and strategies is tighter that the coupling between the abstraction and implementation in the bring pattern.







public interface IBehaviour {
                public int moveCommand();
}

public class Fast implements IBehaviour{
                public int moveCommand()
                {
                                System.out.println("\tFast Behaviour: Wont go beyond 200 kph");
                                return 1;
                }
}

public class Moderate implements IBehaviour{
                public int moveCommand()
                {
                                System.out.println("\Moderate Behaviour: Wont go beyond 150 kph");
                                return -1;
                }
}

public class Slow implements IBehaviour{
                public int moveCommand()
                {
                                System.out.println("\tSlow Behaviour: Wont go beyond 100 kph");
                                return 0;
                }
}

public class Car {
                IBehaviour behaviour;
                String name;

                public Car(String name)
                {
                                this.name = name;
                }

                public void setBehaviour(IBehaviour behaviour)
                {
                                this.behaviour = behaviour;
                }

                public IBehaviour getBehaviour()
                {
                                return behaviour;
                }

                public void move()
                {
                                System.out.println(this.name + ": Based on current position" +
                                                                                 "the behaviour object decide the next move:");
                                int command = behaviour.moveCommand();
                                // ... send the command to mechanisms
                                System.out.println("\tThe result returned by behaviour object " +
                                                                                "is sent to the movement mechanisms " +
                                                                                " for the Car '"  + this.name + "'");
                }

                public String getName() {
                                return name;
                }

                public void setName(String name) {
                                this.name = name;
                }
}


public class Main {

                public static void main(String[] args) {

                                Car r1 = new Car("Honda City");
                                Car r2 = new Car("Swift");
                                Car r3 = new Car("Nano");

                                r1.setBehaviour(new Fast());
                                r2.setBehaviour(new Moderate());
                                r3.setBehaviour(new Slow());

                                r1.move();
                                r2.move();
                                r3.move();

                                r1.setBehaviour(new Moderate());
                                r2.setBehaviour(new Fast());

                                r1.move();
                                r2.move();
                                r3.move();
                }
}


Singleton pattern

A singleton is a class that can be instantiated only one time in a JVM per class loader. Repeated calls always
return the same instance. Ensures that a class has only one instance, and provide a global point of access. It
can be an issue if singleton class gets loaded by multiple class loaders.

public class OnlyOne {
             private static OnlyOne one = new OnlyOne();
             private OnlyOne(){… } //private constructor. This class cannot be instantiated from outside.
             public static OnlyOne getInstance() {
                           return one;
                           }
                }


To use it:
//No matter how many times you call, you get the same instance of the object.
OnlyOne myOne = OnlyOne.getInstance();

Note: The constructor must be explicitly declared and should have the private access modifier, so that it cannot be
instantiated from out side the class. The only way to instantiate an instance of class OnlyOne is through the getInstance() method with a public access modifier.

When to use: Use it when only a single instance of an object is required in memory for a single point of access.

For example the following situations require a single point of access, which gets invoked from various parts of
the code.

􀂃 Accessing application specific properties through a singleton object, which reads them for the first time from
a properties file and subsequent accesses are returned from in-memory objects. Also there could be
another piece of code, which periodically synchronizes the in-memory properties when the values get
modified in the underlying properties file. This piece of code accesses the in-memory objects through the
singleton object (i.e. global point of access).

􀂃 Accessing in-memory object cache or object pool, or non-memory based resource pools like sockets,
connections etc through a singleton object (i.e. global point of access).
What is the difference between a singleton class and a static class? Static class is one approach to make a class singleton
by declaring the class as “final” so that it cannot be extended and declaring all the methods as static so that you can’t create any
instance of the class and can call the static methods directly.




A Factory method pattern (aka Factory pattern) is a creational pattern. The creational patterns abstract the object instantiation process by hiding how the objects are created and make the system independent of the object creation process. An Abstract factory pattern is one level of abstraction higher than a factory method pattern,
which means it returns the factory classes.

Factory method pattern (aka Factory pattern)

Factory for what? Factory pattern returns one of the several product subclasses. You should use a factory pattern If you have a super class and a number of subclasses, and based on some data provided, you have to return the object of one of the subclasses.

 Let’s look at a sample code:


public interface Const {
             public static final int SHAPE_CIRCLE =1;
             public static final int SHAPE_SQUARE =2;
             public static final int SHAPE_HEXAGON =3;
        }


public class ShapeFactory {
             public abstract Shape getShape(int shapeId);
     }


public class SimpleShapeFactory extends ShapeFactory throws BadShapeException {

public Shape getShape(int shapeTypeId) {

Shape shape = null;

if(shapeTypeId == Const.SHAPE_CIRCLE) {
             //in future can reuse or cache objects.
             shape = new Circle();
    }
else if(shapeTypeId == Const.SHAPE_SQUARE) {
             //in future can reuse or cache objects
             shape = new Square();
     }
else throw new BadShapeException
             (“ShapeTypeId=”+ shapeTypeId);

return shape;
       }
}



Now let’s look at the calling code, which uses the factory:

ShapeFactory factory = new SimpleShapeFactory();
//returns a Shape but whether it is a Circle or a
//Square is not known to the caller.
Shape s = factory.getShape(1);
s.draw(); // circle is drawn
//returns a Shape but whether it is a Circle or a
//Square is not known to the caller.
s = factory.getShape(2);
s.draw(); //Square is drawn



Abstract factory pattern


An Abstract factory pattern is one level of abstraction higher than a factory method pattern, which means the abstract factory returns the appropriate factory classes, which will later on return one of the product subclasses.

 Let’s look at a sample code:
public class ComplexShapeFactory extends ShapeFactory {
throws BadShapeException {

public Shape getShape(int shapeTypeId){

Shape shape = null;

if(shapeTypeId == Const.SHAPE_HEXAGON) {
               shape = new Hexagon();//complex shape
}
else throw new BadShapeException(“shapeTypeId=” + shapeTypeId);
              return shape;
}
}


Now let’s look at the abstract factory, which returns one of the types of ShapeFactory:

public class ShapeFactoryType throws BadShapeFactoryException {

public static final int TYPE_SIMPLE = 1;
public static final int TYPE_COMPLEX = 2;


public ShapeFactory getShapeFactory(int type) {

            ShapeFactory sf = null;
                  if(type == TYPE_SIMPLE) {
                           sf = new SimpleShapeFactory();
                       }
                  else if (type == TYPE_COMPLEX) {
                          sf = new ComplexShapeFactory();
                        }
                  else throw new BadShapeFactoryException(“No factory!!”);

               return sf;
            }
}


Now let’s look at the calling code, which uses the factory:

ShapeFactoryType abFac = new ShapeFactoryType();
ShapeFactory factory = null;
Shape s = null;
//returns a ShapeFactory but whether it is a SimpleShapeFactory or a ComplexShapeFactory is not known to the caller.
factory = abFac.getShapeFactory(1);//returns SimpleShapeFactory
//returns a Shape but whether it is a Circle or a Pentagon is not known to the caller.
s = factory.getShape(2); //returns square.
s.draw(); //draws a square
//returns a ShapeFactory but whether it is a SimpleShapeFactory or a ComplexShapeFactory is not known to the caller.
factory = abFac.getShapeFactory(2);
//returns a Shape but whether it is a Circle or a Pentagon is not known to the caller.
s = factory.getShape(3); //returns a pentagon.
s.draw(); //draws a pentagon


Why use factory pattern or abstract factory pattern?

Factory pattern returns an instance of several (product hierarchy) subclasses (like Circle, Square etc), but the calling code is unaware of the actual implementation class.

The calling code invokes the method on the interface (for example Shape) and using polymorphism the correct draw() method gets invoked . So, as you can see, the factory pattern reduces the coupling or the dependencies between the calling code and called objects like Circle, Square etc. This is a very powerful and common feature in many frameworks. You do not have to create a new Circle or a new Square on each invocation as shown in the sample code, which is for the purpose of illustration and simplicity. In future, to conserve memory you can decide to cache objects or reuse objects in your factory with no changes required to your calling code. You can also load objects in your factory based on attribute(s) read from an external properties file or some other condition. Another benefit going for the factory is that unlike calling constructors directly, factory patterns have more meaningful names like getShape(…), getInstance(…) etc, which may make calling code more clear.



Can we use the singleton pattern within our factory pattern code?

 Yes. Another important aspect to consider when writing your factory class is that, it does not make sense to create a new factory object for each invocation as it is shown in the sample code, which is just fine for the illustration purpose.

ShapeFactory factory = new SimpleShapeFactory();

To overcome this, you can incorporate the singleton design pattern into your factory pattern code. The singleton design pattern will create only a single instance of your SimpleShapeFactory class. Since an abstract factory pattern is unlike factory pattern, where you need to have an instance for each of the two factories (i.e. SimpleShapeFactory and ComplexShapeFactory) returned, you can still incorporate the singleton pattern as an access point and have an instance of a HashMap, store your instances of both factories. Now your calling method uses a static method to get the same instance of your factory, hence conserving memory and promoting object

reuse:
ShapeFactory factory = ShapeFactory. Ge/tFactoryInstance();
factory.getShape();






No comments:

Post a Comment