Tuesday, October 26, 2010

Adapter

A method to make use of legacy code or different interface, by means of adapting it to required interface. We go for adapter pattern when the consumed class is not in this developers control as against the bridge pattern where a common interface is agreed.
In java its object adapter pattern, where the adapter will have a reference to the legacy class.

Legacy interface
public class LegacyActionPerformer {

    public void performAction(String action){
        System.out.println("Performing action: "+action);
    }
} 
New Interface
 public interface INewActionPerformer {

    public void performNewAction(String action);
}
Adapter
public class ActionAdapter implements INewActionPerformer{

 private LegacyActionPerformer performer=new LegacyActionPerformer();

 public void performNewAction(String action) {
  performer.performAction(action);
  
 }
}
Client
public class AdapterClient {

    public static void main(String...strings ){
        new ActionAdapter().performNewAction("create a new world");
    }
} 

Bridge

Strategy to bridge two perpendicular developments. This method decouples implementation and the client code.

We will have an interface which the client uses to consume the implementation via an abstraction. The implementation of the interface registers itself with the abstraction.
public interface IActionPerformer {

    public void performAction();
}
Abstraction
public class ActionController {

    private static Set<IActionPerformer> performers=new HashSet<IActionPerformer>();
    
    public static boolean registerPerformer(IActionPerformer performer){
        return performers.add(performer);
    }
    
    public static void perform(){
        Iterator it=performers.iterator();
        ((IActionPerformer)it.next()).performAction();
    }
}
Implementation
public class ActionPerformerImpl implements IActionPerformer {

    static{
        ActionController.registerPerformer(new ActionPerformerImpl());
    }
    public void performAction() {
        System.out.println("this impl can be independent of client");
    }
} 
the client
public class ActionClient {

    public static void main(String...strings ){
        try {
            Class.forName("dp.bridge.ActionPerformerImpl");
        } catch (ClassNotFoundException e) {}
        ActionController.perform();
    }
} 

Sunday, October 24, 2010

Builder

Large value object built in parts, with the help of a director building the object.

A large value object
public class FlightCrew {

 CabinCrew ccrew;
 GroundCrew gcrew;
 PilotCrew pcrew;
 
 public void setCabinCrew(CabinCrew crew){
  ccrew=crew;
 }
 public void setGroundCrew(GroundCrew crew){
  gcrew=crew;
 }
 public void setPilotCrew(PilotCrew crew){
  pcrew=crew;
 }
 public String toString(){
  return ccrew+"\n"+gcrew+" \n"+pcrew;
 }
}
a director to build object part by part
public class FlightDirector {

 public FlightCrew fcrew=new FlightCrew();
 
 private void buildCabinCrew(){
  //read from database available crew
  fcrew.setCabinCrew(new CabinCrew(new String[]{"Tom","Dave"}));
 }
 private  void buildGroundCrew(){
  fcrew.setGroundCrew(new GroundCrew(new String[]{"Charles","John"}));
 }
 private void buildPilotCrew(){
  fcrew.setPilotCrew(new PilotCrew(new String[]{"Austin"}));
 }
 public FlightCrew buildFlightCrew(){
  buildCabinCrew();
  buildGroundCrew();
  buildPilotCrew();
  return fcrew;
 }
} 

the client
public class FlightOperations {

 public static void main(String...strings){
  FlightCrew crew=new FlightDirector().buildFlightCrew();
  System.out.println("The Flight Crew");
  System.out.println(crew);
 }
}
output
The Flight Crew
Cabin Crew:
    Tom,Dave
Ground Crew:
    Charles,John 
Pilot Crew:
    Austin 

Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.

Saturday, October 23, 2010

Prototype

Prototype object when its creation gets expensive.
Actual object,
public class ExpensiveType implements Cloneable {

    public int i=0;
    public ExpensiveType(){
        System.out.println("Expensive Object creation");
        i=new Random(10).nextInt();
    }
    public int getI(){
        return i;
    }
    public void setI(int i){
        this.i=i;
    }
    public ExpensiveType clone() throws CloneNotSupportedException{
        ExpensiveType clone=(ExpensiveType)super.clone();
        return clone;
    }
} 
A factory to hold reference to once created expensive object,
public class PrototypeFactory {

    private PrototypeFactory(){}
    private static PrototypeFactory s_instance=new PrototypeFactory();
    public static PrototypeFactory getInstance(){
        return s_instance;
    }
    private ExpensiveType actualObject=null;
    public  ExpensiveType prototypeExpensiveObject() throws CloneNotSupportedException{
        if(actualObject==null)
            actualObject=new ExpensiveType();
        return (ExpensiveType) actualObject.clone(); 
    }
} 
client,
public class ActualObjectClient {

    public static void main(String...strings ){
        try {
            ExpensiveType object=PrototypeFactory.getInstance().prototypeExpensiveObject();
            System.out.println(object.getI());
            object.setI(99);
            System.out.println(object.getI());
            object=PrototypeFactory.getInstance().prototypeExpensiveObject();
            System.out.println(object.getI());
        } catch (CloneNotSupportedException e) {
        }
    }
} 
sample output,
Expensive Object creation
-1157793070
99
-1157793070

Lazy Initialization

The tactic of delaying object creation or module initialization(modules pattern) up until it is required.

We have
Initializable interface: which is where initialization happen,

public interface Initializable {
    public void init();
    public boolean initialized();
    public boolean isLazyInit();
    public void setInited(boolean status);
    public String getName();
} 
InitializationDirector : which does the initialization of required object,
public class InitializationManager {

 public static void  initialize(String module){
  for(Initializable registered:InitializableRegistry.getInits()){
   if(registered.name().equalsIgnoreCase(module))
    initialize(registered);
  }
 }
 public static void initAll(){
  for(Initializable registered:InitializableRegistry.getInits()){
   initialize(registered);
  }
 }
 public static void initialize(Initializable initializable){
  if(!initializable.initialized()){
   initializable.init();
   initializable.setInited(true);
  }
 }
}

InitializableRegistry  : registry of all initializables
public class InitializableRegistry {

 private static List<Initializable> initializables=new ArrayList<Initializable>(5);
 public static void registerInitializable(Initializable init){
  if(!init.isLazyInit()){
   System.out.println("initializing "+init.name()+" on registeration");
   init.init();
   init.setInited(true);
  }
  initializables.add(init);
 }
 public static List<Initializable> getInits(){
  return initializables;
 }
} 
Test,
public class LazyInitDemo {

 public static void main(String[] args) {
  InitializableRegistry.registerInitializable(new EngineCheck());
  InitializableRegistry.registerInitializable(new EmergencySetups());
  InitializableRegistry.registerInitializable(new AutoPilot());
  InitializableRegistry.registerInitializable(new FlightPath());
  
  System.out.println("---lazy init on demand of particular module");
  InitializationManager.initialize("FlightPath");
  
  System.out.println("---init whatever is left");
  InitializationManager.initAll();
 }
} 
sample output
initializing EngineCheck on registeration
initing Engine check
initializing Emergency on registeration
initing emergency modules
---lazy init on demand of particular module
initing FlightPath module
---init whatever is left
initing AutoPiloting