Showing posts with label design. Show all posts
Showing posts with label design. Show all posts

Monday, March 18, 2013

Factory Method Pattern

The Factory Method Pattern encapsulates object creation by letting subclasses decide what objects to create. The creator class defines an abstract factory method that the subclasses implement to produce products. Factory method is known as a creational pattern - it's used to construct objects such that they can be decoupled from the implementing system.

The GoF book on Design Patterns defines it as -
Define an interface for creating an object, but let the subclasses decide which class to instantitate. The Factory method lets a class defer instantiation to subclasses.
In this definition the term "interface" is used in the general sense, meaning - a concrete class implementing a method from a supertype (a class or interface).

The Factory method builds on the concept of a Simple Factory, but lets the sub-classes decide which implementation of the concrete class to use. Simple factory is a programming idiom rather than a pattern, where object creation is relegated to a method. Factory Method pattern builds on it - deferring object creation to sub-classes.

A simple factory can also be defined as a static method and is often called a static factory. This way we don’t have to instantiate an object to make use of the create method. But the disadvantage is that, we can’t subclass and change the behavior of the create method.

Example code from http://java.dzone.com/articles/design-patterns-factory. First an interface and an implementation for the product:

public interface Logger {
	public void log(String message);
}
public class XmlLogger implements Logger {

	@Override
	public void log(String message) {
		System.err.println(message);
	}

}
Creator with the abstract factory method:
public abstract class AbstractLoggerCreator {
	
	//factory method
	public abstract Logger createLogger();
	
	public Logger getLogger() {
		Logger logger = new XmlLogger();
		return logger;
	}
}
Now the concrete creator class:
public class XmlLoggerCreator extends AbstractLoggerCreator {
	@Override
	public Logger createLogger() {
		XmlLogger logger = new XmlLogger();
		return logger;
	}
}
Finally the client code to test the pattern:
public class FactoryMethodClient {
	private void methodA(AbstractLoggerCreator creator) {
		Logger logger = creator.createLogger();
		logger.log("message");
	}

	public static void main(String[] args) {
		AbstractLoggerCreator creator = new XmlLoggerCreator();
		FactoryMethodClient client = new FactoryMethodClient();
		client.methodA(creator);
	}

}
Downside of the pattern is that it might be over-complicated. In a lot of cases, a simple factory pattern will work fine. The FactoryMethod just allows further decoupling, leaving it to the sub-classes of the Creator to decide which type of concrete Product to create.

Thursday, March 07, 2013

Data Structures - Queue

A Queue is an example of a linear data structure - a sequential
collection, and it is a FIFO structure. Anything that's inserted
first, will be the first to leave. We need to maintain two pointers,
the start and the end. An efficient implementation of Queue performs
the operations - enqueue (insert) and dequeue (remove) - in O(1) time.

Below is a sample implementation of a Queue (Java Data Structures (2nd edition))

public class Queue {
 private Object[] objArray;
 private int start, end;
 private boolean full;

 public Queue(final int maxSize) {
  objArray = new Object[maxSize];
  start = end = 0;
  full = false;
 }

 public boolean isEmpty() {
  return (start == end) && !full;
 }

 public boolean isFull() {
  return full;
 }

 public void insert(final Object o) {
  if (!full) {
   objArray[start = (++start % objArray.length)] = o;
  }
  

  if (start == end) {
   full = true;
  }
 }

 public Object remove() {
  if (full) {
   full = false;
  } else if (isEmpty()) {
   return null;
  }

  return objArray[end = (++end % objArray.length)];
 }

 public String toString() {
  StringBuilder sbr = new StringBuilder();
  for (int i = 0; i < objArray.length; i++) {
   sbr.append(objArray[i]);
  }
  return sbr.toString();
 }
}

Wednesday, March 03, 2010

Adapter Pattern

-  The adapter acts as the middleman by receiving requests from the client and converting them into requests that make sense on the vendor classes

­-  The adapter implements the target interface and holds an instance of the adaptee

-  The actual interface that the client needs is the target interface

-  We wrap the target interface with an adaptee interface, which does the work of the target interface

-  The client makes the request on the adapter, and the adapter delegates it to the adaptee interface

-  The client doesn't know that the actual work was done by the adaptee

-  Client and the adaptee are decoupled – neither knows about the other

-  Here's how the client uses the adapter

o        The client makes a request to the adapter by calling a method on it using the target interface

o        The adapter translates that request into one or more calls on the adaptee using the adaptee interface

o        The client receives the results of the call and never knows there is an adapter doing the translation

­           

­-  The Adapter Pattern converts the interface of a class into another interface the clients expect

­-  Adapter lets classes work together that couldn't otherwise because of incompatible interfaces

­-  This decouples the client from the implemented interface,

­-  If the interface changes over time, the adapter encapsulates the change so that the client doesn't have to be modified each time it needs to operate against a different interface

­-  It is not necessary that the adapter should wrap only one adaptee – it can hold two or more adaptees that are need to implement the target interface

 

­- There are two types of adapters

o        object adapters – uses composition - the adapter is composed of adaptee

§         it can not only adapt an adaptee class, but any of its subclasses

o        class adapters – uses multiple inheritance - the adapter subclasses both the target and the adaptee

§         it is committed to one specific adaptee class, but it doesn't have to reimplement the entire adaptee

§         it can also override the behavior of the adaptee, since its just subclassing

§         this cannot be used in Java since it involves multiple inheritance

 

­- Although Decorator and Adapter patterns looks similar, they are totally different in intent

o        Decorator wraps an object and adds new behavior

o        Adapter wraps an object and converts it into an interface the client expects

 

­- Following is an example of Adapter pattern. This example adapts an Enumerator to act as an Iterator

	public class EnumerationAdapter implements Iterator {

Enumeration enumeration;
public EnumerationAdapter(Enumeration enumeration) {
this.enumeration = enumeration;
}
public boolean hasNext() {
enumeration.hasMoreElements();
}
public Object next() {
enumeration.nextElement();
}
public void remove() {
throw new UnsupportedOperationException();
}
}

Monday, September 01, 2008

Façade Pattern

  • ­          A facade hides all the complexity of one or more classes
  • ­          Similar to Adapter pattern, it alters an interface, but for a different reason – to simplify the interface
  • ­          Façades and adapters may wrap multiple classes, but a façade's intent is to simplify, while an adapter's is to convert the interface to something different
  • ­          A façade not only simplifies an interface, it decouples a client from a subsystem of components
  • ­          It provides a simplified interface while still exposing the full functionality of the system to those who may need it
  • ­          Façades don't encapsulate the subsystem classes – they merely provide a simplified interface to their functionality
  • ­          The subsystem classes still remain available for direct use by clients that need to use more specific interfaces
  • ­          The façade can also add additional functionality in addition to making use of the subsystem
  • ­          It is not necessary that each subsystem should have only one façade, any number of façades can be created for a given subsystem
  • ­          Following is an example of a façade for a home theater system

public class HomeTheaterFacade {

      Amplifier amp;

      DvdPlayer dvd;

      Projector projector;

      Screen screen;

      Tuner tuner;

 

      public HomeTheaterFacade(Amplifier amp,

                              DvdPlayer dvd,

                              Projector projector,

                              Screen screen,

                              Tuner tuner) {

            this.amp = amp;

            this.dvd = dvd;

            this.projector = projector;

            this.screen = screen;

            this.tuner = tuner;

      }

 

      public void watchMovie() {

      }

 

      public void endMovie() {

      }

}

­           

  • ­          The Façade Pattern provides a unified interface to a set of interfaces in a subsystem
  • ­          Façade defines a higher-level interface that makes the subsystem easier to user
  • ­          To use the façade pattern, we create a class that simplifies and unifies a set of more complex classes that belong to some subsystem
  • ­          It allows us to avoid tight coupling between clients and subsystems­     

Friday, August 22, 2008

Composition vs. Aggregation

Composition


  • Composition allows us to use behavior from a family of other classes, and to change that behavior at runtime
  • Composition is most powerful when we want to use behavior defined in an interface, and then choose from a variety of implementations of that interface, at both compile time and run time
  • Composition is like a string "has a" relationship - the components that make up the parent cannot existing without the parent
  • When an object is composed of other objects, and the owning object is destroyed, the objects that are part of the composition goes away too
  • A real world example may be - a human body is composed of different parts hands, legs etc. But without the body, the parts cannot exist alone
  • A code example using a car example
    Car car = new  Car();
    car.setProperty("engine", new Engine());
  • When the "car" object is destroyed, so is the Engine object created in the second line. It is destroyed along with the owning object
  • Simply there is no reference for the component object outside the owning object


  • In composition, the object composed of other behaviors owns those behaviors
  • When the object is destroyed, so are all of its behaviors
  • The behaviors in a composition do not exist outside of the composition
  • The main object owns the composed behavior, so if that object goes away, all the behavior does too
  • The UML diagram for composition uses a darkened diamond - signifying the strong relationship





Aggregation


  • Aggregation is when one class is used as part of another class, but still exists outside of that other class
  • Aggregation is a kind of association that specifies a whole/part relationship between the aggregate(whole) and component part
  • This relationship between the aggregate and component is a weak "has a" relationship as the component may survive the aggregate object
  • Unlike composition, here, the component object may outlive the aggregate object
  • A code example using a Course/Student example
    course.addStudent(student);
  • The student object has its own behavior, and its state can influence the state of the course object (for instance, the aggregate mark for the course etc.)
  • Even if the course object is destroyed, student object will live on

  • The UML diagram for aggregation uses an empty diamond





Aggregation vs. Composition


  • The easiest way to figure out when to use what is to ask - does the object whose behavior I want to use exist outside of the object that uses its behavior?
  • If the object does make sense existing on its own, then we should use aggregation, if not use composition

Tuesday, November 06, 2007

Singleton Pattern

  • The Singleton Pattern ensures a class has only one instance, and provides a global point of access to it
  • Singleton pattern assures that at any one time there is only one instance of the class
  • It is used where an instance can take consume large amount of resources
  • It is used to manage pools of resources, like connection or thread pools
  • A singleton class doesn't have a public constructor
  • An instance of the class can be obtained by calling a static method of the class which will return an unique instance
  • Java's implementation of the Singleton Pattern makes use of a private constructor, a static method combined with a static variable. Sample code:
    public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
    if(instance == null)
    instance = new Singleton();
    return instance;
    }
    }
  • The above code works fine - but only to some extent
  • When there are multiple threads accessing getInstance(), above code will no longer work as expected, it can give out multiple instances of the object
  • One simple solution is to make the method synchronized
    public static Synchronized Singleton getInstance()
  • But making a method synchronized affects performance by a factor of 100
  • Another option is to use eager instantiation rather than lazy instantiation, i.e., create the instance upfront, instead of creating it inside the getInstance() method. In this case JVM will make sure that the instance is created before any thread can access the static variable 'instance'.
    public class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
    return instance;
    }
    }
  • Usage of double-checked locking will reduce the overhead of using synchronized keyword drastically. But it doesn't work Java 1.4 or earlier:
    public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
    if(instance == null) {
    synchronized(Singleton.class) {
    if(instance == null) {
    instance = new Singleton();
    }
    }
    }
    return instance;
    }
    }
  • A singleton class cannot be subclassed, since the constructor is private
  • If multiple class loaders are being used, as each ckass kiader defines a namespace, multiple instances of the Singleton class will get created


(Ref: Chapter 5 - One of a Kind Objects, Head First Design Pattern)