Bridge pattern

Bridge pattern is structural design pattern.

Motive: Decouple an abstraction or interface from its implementation so that the two can vary independently.

Where To Use

  1. Want to separate abstraction and implementation permanently
  2. Hide implementation details from clients
  3. Want to improve extensibility

Real Life Example: In real life scenario bridge pattern is used for persistence API. While writing application layer developer want to fetch information from persistence system (E.g. Database or File System). In this scenario there are two interface at

a) Application layer – Where end client is routed
b) Persistance layer – Interface define persist/fetch

To have flexible design one would like to decouple application layer from persistence API. I.e. I want to have flexibility to use any persistence system (Database, File System, via JMS Etc). Below sample example explain bridge design pattern to improve extensibility.

Class Diagram: Please open class diagram in new window if problem occurs.

Bridge Pattern Class Diagram

Application Code

Abstraction Interface: – Persistence

package com.structural.bridge.application;

import com.structural.bridge.apptopersisterbridge.PersistenceImplementor;

/**
 * This is abstraction Interface.
 *
 * @author Shishir Kumar
 */
public abstract class Persistence {
 private PersistenceImplementor persistanceImplementor = null;
 
 /**
  * Constructor.
  * @param implementer
  */
 public Persistence(PersistenceImplementor implementer){
  this.persistanceImplementor = implementer;
 }
 
 /**
  * Persist Object.
  * @param object
  * @return returns objectID
  */
 public abstract String persist(Object object);
 
 /**
  * Find record by primary key.
  * @param objectId
  * @return persisted Object
  */
 public abstract Object findById(String objectId);
 
 /**
  * Delete record by primary key.
  * @param id
  */
 public abstract void deleteById(String id);
 
 /**
  * Getter for PersistenceImplementor.
  * @return PersistenceImplementor
  */
 public PersistenceImplementor getPersistanceImplementor() {
  return persistanceImplementor;
 }

 /**
  * Setter for PersistenceImplementor.
  * @param persistanceImplementor Input persistence implementor
  */
 public void setPersistanceImplementor(
   PersistenceImplementor persistanceImplementor) {
  this.persistanceImplementor = persistanceImplementor;
 } 
}

Abstraction Interface Implementation: – PersistanceImpl

package com.structural.bridge.application;

import com.structural.bridge.apptopersisterbridge.PersistenceImplementor;

/**
 * Persistence Implementation. This is abstraction interface implementation.
 *
 * @author Shishir Kumar
 */
public class PersistenceImpl extends Persistence {

 /**
  * Constructor.
  * @param implementer
  */ 
 public PersistenceImpl(PersistenceImplementor implementer) {
  super(implementer);
 }

 /**
  * Persist Object.
  * @param object
  * @return returns objectID
  */
 public void deleteById(String id) {
  getPersistanceImplementor().deleteObject(Long.parseLong(id));
 }

 /**
  * Find record by primary key.
  * @param objectId
  * @return persisted Object
  */
 public Object findById(String objectId) {
  return getPersistanceImplementor().getObject(Long.parseLong(objectId));
 }

 /**
  * Persist Object.
  * @param object
  * @return returns objectID
  */
 public String persist(Object object) {
  return Long.toString(getPersistanceImplementor().saveObject(object));
 }
}

Bridge: Interface acts as bridge between application and persistance system.

package com.structural.bridge.apptopersisterbridge;

/**
 * All Method within this class should be implemented by source/company
 * providing persistance implementation for application developer. This acts as
 * bridge interface between application user and persistance implementation
 * (DB/FileSystem) provider.
 *
 * @author Shishir Kumar
 */
public interface PersistenceImplementor {

 /**
  * This method should provide implementation to save object.
  * @param object to save.
  * @return unique identifier.
  */
 public long saveObject(Object object);

 /**
  * This method should provide implementation to delete object based on input
  * key.
  *
  * @param objectId input objectId to be deleted.
  */
 public void deleteObject(long objectId);
 
 /**
  * This method should provide implementation to extract object based on input
  * key.
  *
  * @param objectId
  * @return
  */
 public Object getObject(long objectId);

}

Persistance Layer

FileSystem Implementor

package com.structural.bridge.filesystem;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;

import com.structural.bridge.apptopersisterbridge.PersistenceImplementor;

/**
 * Concrete Implementor to persist data to filesystem.
 * 
 * @author Shishir.Kumar
 */
public class FileSystemPersistenceImplementor implements PersistenceImplementor {

 public FileSystemPersistenceImplementor(){
  // load database driver
 }

 /**
  * This method provide implementation to delete record based on input key.
  *
  * @param objectId input objectId to be deleted.
  */
 public void deleteObject(long objectId) {
  File f = new File(“/persistence/”+Long.toString(objectId));
  f.delete();
  return;

 }

 /**
  * This method provide implementation to extract object based on input key.
  *
  * @param objectId
  * @return
  */
 public Object getObject(long objectId) {
  String fileName = new Long(objectId).toString() + “.txt”;
  return readObjectFromFile(fileName);
 }

 /**
  * This method provide implementation to save object.
  * @param object to save.
  * @return unique identifier.
  */
 public long saveObject(Object object) {
  long fileId = System.currentTimeMillis();
  String fileName = new Long(fileId).toString() + “.txt”;
  // write file to Streanm
  writeObjectToFile(fileName,object);
  return fileId;
 }

    /**
     * Prints some data to a file using a BufferedWriter
     */
    public void writeObjectToFile(String filename,Object object) {
       
        BufferedWriter bufferedWriter = null;
       
        try {
           
            //Construct the BufferedWriter object
            bufferedWriter = new BufferedWriter(new FileWriter(filename));
           
            //Start writing to the output stream
            bufferedWriter.write(object.toString());
           
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            //Close the BufferedWriter
            try {
                if (bufferedWriter != null) {
                    bufferedWriter.flush();
                    bufferedWriter.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
 private Object readObjectFromFile(String fileName) {
  StringBuffer returnData = new StringBuffer();
  try {
   // Open the file that is the first
   // command line parameter
   FileInputStream fstream = new FileInputStream(fileName);
   // Get the object of DataInputStream
   DataInputStream in = new DataInputStream(fstream);
   BufferedReader br = new BufferedReader(new InputStreamReader(in));
   String strLine;
   // Read File Line By Line
   while ((strLine = br.readLine()) != null) {
    // Print the content on the console
    returnData.append(strLine + “\n”);
   }
   // Close the input stream
   in.close();
  } catch (Exception e) {// Catch exception if any
   System.err.println(“Error: ” + e.getMessage());
  }
  return returnData;
 }
}

Database Persistance Implementor

package com.structural.bridge.database;

import com.structural.bridge.apptopersisterbridge.PersistenceImplementor;

/**
 * Concrete Implementor to persist data to database.
 * 
 * @author Shishir.Kumar
 */
public class DatabasePersistenceImplementor implements PersistenceImplementor {

 public DatabasePersistenceImplementor() {
  // load database driver
 }

 /**
  * This method provide implementation to delete object based on input key.
  *
  * @param objectId input objectId to be deleted.
  */
 public void deleteObject(long objectId) {
  // open database connection
  // remove record
 }

 /**
  * This method provide implementation to extract object based on input key.
  *
  * @param objectId
  * @return
  */
 public Object getObject(long objectId) {
  // open database connection
  // read records
  // create object from record
  return null;
 }

 /**
  * This method provide implementation to save object.
  * @param object to save.
  * @return unique identifier.
  */
 public long saveObject(Object object) {
  // open database connection
  // create records for fields inside the object
  return 0;
 }

}

How Adaptor and Bridge are different?

  • Bridge pattern separates the interface from implementation. 
  • Bridge pattern should be used when both the class as well as what it does very often.
  • Abstractions and implementations should not be bound at compile time, and should be independently extensible the pattern should be used. 

Please share your feedback/query.

Should Read: Adapter Pattern

Next In Store: Template Pattern

One Response to Bridge pattern

  1. Awanish Atul says:

    Good explanation for bridge pattern!!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: