Design patterns - Abstract Factory with Java Example

Introduction

Abstract Factory design pattern comes under creational design pattern. It is also called factory of factories. It provides a way to encapsulate a group of factories which have common behaviour or theme without specifying which underlying concrete objects are created. It is one level of abstraction higher than Factory pattern. In Factory Design Pattern, we get instance of one of several sub-classes whereas in Abstract Factory Design pattern we get instance of one of several factories which then get instance of one of several sub-classes.

Implementation

We are going to create Factories for Import and Export. We have one producer class ImportExportFactoryProducer which produces the factory based on type i,e. if instance of ImportFactory is required or ExportStrategy is required which then initialize the concrete classes for ImportStrategy or ExportStrategy.

1. AbstractFactoryTest class

package com.gauravbytes.test;

import com.gauravbytes._import.ImportStrategy;import com.gauravbytes.export.ExportStrategy;import com.gauravbytes.importexport.factory.AbstractImportExportFactory;import com.gauravbytes.importexport.factory.ImportExportFactoryProducer;import com.gauravbytes.importexport.factory.ImportExportFactoryTypes;

/**
 * @author Gaurav Rai Mazra
 */
public class AbstractFactoryTest {

 public static void main(String[] args) {
  int factoryType = ImportExportFactoryTypes.TYPE_EXPORT;
  int strategyType = AbstractImportExportFactory.TYPE_EXCEL;
  
  AbstractImportExportFactory ioFactory = ImportExportFactoryProducer.getInstance().getFactory(factoryType);
  
  switch (factoryType) {
   case ImportExportFactoryTypes.TYPE_EXPORT :
    ExportStrategy exportStrategy = ioFactory.getExportStrategy(strategyType);
    exportStrategy.export();
    break;
    
   case ImportExportFactoryTypes.TYPE_IMPORT : 
    ImportStrategy importStrategy = ioFactory.getImportStrategy(strategyType);
    importStrategy.importFile();
    break;
   default:
    break;
  }
 }
}

2. FactoryProducer class, In our case ImportExportFactoryProducer

package com.gauravbytes.importexport.factory;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * This is Factory producer class
 * @author Gaurav Rai Mazra
 *
 */
public class ImportExportFactoryProducer {
 private static ImportExportFactoryProducer factoryInstance = null;
 private static final Lock lock = new ReentrantLock();
 private ImportExportFactoryProducer() {
  
 }
 
 public static ImportExportFactoryProducer getInstance() {
  try {
   lock.lock();
   if (factoryInstance == null)
    factoryInstance = new ImportExportFactoryProducer();
  }
  finally {
   lock.unlock();
  }
  return factoryInstance;
 }
 
 
 public AbstractImportExportFactory getFactory(int factoryType) {
  AbstractImportExportFactory factory = null;
  switch (factoryType) {
   case ImportExportFactoryTypes.TYPE_IMPORT:
    factory = ImportFactory.getInstance(lock);
    break;
    
   case ImportExportFactoryTypes.TYPE_EXPORT:
    factory = ExportFactory.getInstance(lock);
    break;
 
   default:
    break;
  }
  return factory;
 }
}

3. Factory of Factory  and the concrete factories . In our case AbstractImportExportFactory, ImportFactory and ExportFactory.

package com.gauravbytes.importexport.factory;

import com.gauravbytes._import.ImportStrategy;import com.gauravbytes.export.ExportStrategy;

/**
 * This is factory of factory gives the instance for particular strategy
 * @author Gaurav Rai Mazra
 *
 */
public abstract class AbstractImportExportFactory {
 public static final int TYPE_EXCEL = 1;
 public static final int TYPE_PDF = 2;
 public static final int TYPE_PLAIN = 3;
 
 
 public abstract ImportStrategy getImportStrategy(int strategyType);
 public abstract ExportStrategy getExportStrategy(int strategyType);
}
package com.gauravbytes.importexport.factory;

/**
 * @author Gaurav Rai Mazra
 */
public abstract class ImportExportFactoryTypes {
 public static final int TYPE_IMPORT = 1;
 public static final int TYPE_EXPORT = 2;
}
package com.gauravbytes.importexport.factory;

import com.gauravbytes._import.ExcelImport;import com.gauravbytes._import.ImportStrategy;import com.gauravbytes._import.PdfImport;import com.gauravbytes._import.PlainTextImport;import com.gauravbytes.export.ExportStrategy;
import java.util.concurrent.locks.Lock;

/**
 * Import factory
 * @author Gaurav Rai Mazra
 */
public class ImportFactory extends AbstractImportExportFactory {

 private static ImportFactory importFactory = null;
 private ImportFactory() {
  
 }
 
 public static ImportFactory getInstance(Lock lock) {
  try {
   lock.lock();
   if (importFactory == null)
    importFactory = new ImportFactory();
  }
  finally {
   lock.unlock();
  }
  return importFactory;
 }
 
 @Override
 public ImportStrategy getImportStrategy(int strategyType) {
  ImportStrategy importStrategy = null;
  switch (strategyType) {
   case TYPE_EXCEL:
    importStrategy = new ExcelImport();
    break;
   
   case TYPE_PDF:
    importStrategy = new PdfImport();
    break;
    
   case TYPE_PLAIN:
    importStrategy = new PlainTextImport(); 
    break;
 
   default:
    break;
  }
  return importStrategy;
 }

 @Override
 public ExportStrategy getExportStrategy(int strategyType) {
  return null;
 }

}
package com.gauravbytes.importexport.factory;

import com.gauravbytes._import.ImportStrategy;import com.gauravbytes.export.ExcelExport;import com.gauravbytes.export.ExportStrategy;import com.gauravbytes.export.PdfExport;import com.gauravbytes.export.PlainTextExport;
import java.util.concurrent.locks.Lock;


/**
 * Factory to get proper strategy object based on its type
 * @author Gaurav Rai Mazra
 */
public class ExportFactory extends AbstractImportExportFactory {

 private static ExportFactory exportFactory = null;
 
 private ExportFactory() {
  
 }
 
 public static ExportFactory getInstance(Lock lock) {
  try {
   lock.lock();
   if (exportFactory == null)
    exportFactory = new ExportFactory();
  }
  finally {
   lock.unlock();
  }
  return exportFactory;
 }
 
 @Override
 public ImportStrategy getImportStrategy(int strategyType) {
  return null;
 }

 @Override
 public ExportStrategy getExportStrategy(int strategyType) {
  ExportStrategy strategy = null;
  switch (strategyType) {
   case TYPE_EXCEL:
    strategy = new ExcelExport();
    break;

   case TYPE_PDF:
    strategy = new PdfExport();
    break;

   case TYPE_PLAIN:
    strategy = new PlainTextExport();
    break;

   default:
    break;
  }
  return strategy;
 }
}

4. ImportStrategy and their concrete classes

package com.gauravbytes._import;

/**
 * @author Gaurav Rai Mazra
 */
public interface ImportStrategy {
 public void importFile();
}
package com.gauravbytes._import;

/**
 * @author Gaurav Rai Mazra
 */
public class ExcelImport implements ImportStrategy {

 @Override
 public void importFile() {
  // Logic to import excel file goes here
 }

}
package com.gauravbytes._import;

/**
 * @author Gaurav Rai Mazra
 */
public class PdfImport implements ImportStrategy {

 @Override
 public void importFile() {
  //Logic to import pdf goes here
 }

}
package com.gauravbytes._import;

/**
 * @author Gaurav Rai Mazra
 */
public class PlainTextImport implements ImportStrategy {
 @Override
 public void importFile() {
  //Logic to import plain text file
 }
}

5. ExportStrategy with their concrete classes

package com.gauravbytes.export;

/**
 * @author Gaurav Rai Mazra
 */
public interface ExportStrategy {
 public void export();
}
package com.gauravbytes.export;

/**
 * @author Gaurav Rai Mazra
 */
public class ExcelExport implements ExportStrategy {

 @Override
 public void export() {
  // Excel export code goes here
 }

}
package com.gauravbytes.export;

/**
 * @author Gaurav Rai Mazra
 */
public class PlainTextExport implements ExportStrategy {
 @Override
 public void export() {
  // Plain text export goes here
 }
}
package com.gauravbytes.export;

/**
 * @author Gaurav Rai Mazra
 */
public class PdfExport implements ExportStrategy {

 @Override
 public void export() {
  //Pdf export Goes here
 }

}

No comments :

Post a Comment