Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Java

Design Patterns-Simplified

4.74/5 (20 votes)
9 Jul 2015CPOL 24.2K  
This is my humble effort to explain so called complex Design Patterns to explain as simply as possible

Introduction

  • Design patterns have evolved over a long period of time and they provide best solutions to certain problems faced during software development.
  • These solutions were obtained by trial and error by numerous software developers over quite a substantial period of time.
  • Design Principals are abstract ideas and Design Patterns are concrete implementations of those ideas.

Creational Design Pattern

1. SingleTone

Creates only one object:

Image 1

Java
class Singleton {
    private static Singleton uniqueInstance;
    // other useful instance variables here

    private Singleton() {}

    public static Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
    // other useful methods here
}

class SingletonPatternDemo {
    public static void main(String[] args) {
        //Get the only object available
        Singleton object = Singleton.getInstance();
        
        //Singleton object = new Singleton();
        //Compile Time Error: The constructor Singleton() is not visible        
    }
}

2. Factory Pattern

Encapsulate object creational logic – that varies.

Image 2

C#
interface IIceCream
{
    string Functionality();
}

class ChocolateIceCream : IIceCream
{
    public string Functionality()
    {
        return "Chocolate Ice cream";
    }
}

class VanillaIceCream : IIceCream
{
    public string Functionality()
    {
        return "Vanilla Ice cream";
    }
}

class StrawberryIceCream : IIceCream
{
    public string Functionality()
    {
        return "Strawberry Ice cream";
    }
} 

static class Factory
{   
   public static IIceCream Get(int id)
   {
       switch (id)
       {
           case 0:
                return new ChocolateIceCream();
           case 1:
                return new VanillaIceCream();
           case 2:
                return new StrawberryIceCream();
           default:
                return null;
        }
   }
} 

static void Main()
{
   for (int i = 0; i <= 3; i++)
   {
       var type = Factory.Get(i);
       if (type != null)
       {
           Console.WriteLine("This is Product : " + type.Functionality());
       }
   }
} 

3.Abstract Factory

Factory of factories:

Image 3

Real Example:

Image 4

Java
interface Animal{
    void breath();
}

interface LandAnimal extends Animal {
    void speak();
}

interface SeaAnimal extends Animal {
    void swim();
}
Java
class Cat implements LandAnimal {
    @Override
    public void speak() {
        //meow meow
    }
    @Override
    public void breath(){
        //in air
    }
}
class Dog implements LandAnimal {
    @Override
    public void speak() {
        //Bhaow Bhaow
    }
    @Override
    public void breath(){
        //in air
    }
}
class Lion implements LandAnimal {
    @Override
    public void speak() {
        //Big Roar
    }
    @Override
    public void breath(){
        //in air
    }
}
Java
class Shark implements SeaAnimal {
    @Override
    public void swim() {
        //By tail
    }
    @Override
    public void breath(){
        //in water
    }
}
class Whale implements SeaAnimal {
    @Override
    public void swim() {
        //By tail
    }
    @Override
    public void breath(){
        //in water
    }
}
class Octopus implements SeaAnimal {
    @Override
    public void swim() {
        //By arms
    }
    @Override
    public void breath(){
        //in water
    }
}
Java
abstract class AbstractFactory {
    abstract Animal getAnimal(String type);
}
Java
class LandAnimalFactory extends AbstractFactory {
    @Override
    public Animal getAnimal(String type) {
        if (type == null) {
            return null;
        }
        if (type.equalsIgnoreCase("LION")) {
            return (Animal)new Lion();
        } else if (type.equalsIgnoreCase("CAT")) {
            return (Animal)new Cat();
        } else if (type.equalsIgnoreCase("DOG")) {
            return (Animal)new Dog();
        }
        return null;
    }
}
Java
class SeaAnimalFactory extends AbstractFactory {
    @Override
    Animal getAnimal(String type) {
        if (type == null) {
            return null;
        }
        if (type.equalsIgnoreCase("SHARK")) {
            return (Animal)new Shark();
        } else if (type.equalsIgnoreCase("WHALE")) {
            return (Animal)new Whale();
        } else if (type.equalsIgnoreCase("OCTOPUS")) {
            return (Animal)new Octopus();
        }
        return null;
    }
}
Java
class FactoryProducer {
    public AbstractFactory getFactory(String factoryType) {

        if (factoryType.equalsIgnoreCase("LAND")) {
            return new LandAnimalFactory();

        } else if (factoryType.equalsIgnoreCase("SEA")) {
            return new SeaAnimalFactory();
        }

        return null;
    }
}
Java
class AbstractFactoryPatternDemo {
    public static void main(String[] args) {

        FactoryProducer factoryProducer = new FactoryProducer();


        AbstractFactory landAnimalFactory = factoryProducer.getFactory("LAND");

        Animal dog = landAnimalFactory.getAnimal("DOG");
        dog.speak();
        dog.breath();

        Animal cat = landAnimalFactory.getAnimal("CAT");
        cat.speak();
        cat.breath();

        Animal lion = landAnimalFactory.getAnimal("LION");
        lion.speak();
        lion.breath();

        AbstractFactory seaAnimalFactory = factoryProducer.getFactory("SEA");

        Animal shark = seaAnimalFactory.getAnimal("SHARK");
        shark.swim();
        shark.breath();

        Animal whale = seaAnimalFactory.getAnimal("WHALE");
        whale.swim();
        whale.breath();

        Animal octopus = seaAnimalFactory.getAnimal("OCTOPUS");
        octopus.swim();
        octopus.breath();
    }
}

Behavioral Design Pattern

Template Pattern

Image 5

Java
abstract class House {
    abstract void buildFoundation();

    abstract void buildPillars();

    abstract void buildWalls();

    abstract void buildWindows();

    //template method
    public final void contructHouse() {
        buildFoundation();
        buildPillars();
        buildWalls();
        buildWindows();
    }
}
Java
class GlassHouse extends House {

    @Override
    void buildFoundation() {
        //Glass specific procedure
    }

    @Override
    void buildPillars() {
        //Glass specific procedure
    }

    @Override
    void buildWalls() {
        //Glass specific procedure
    }

    @Override
    void buildWindows() {
        //Glass specific procedure
    }
}
Java
class WoodenHouse extends House {

    @Override
    void buildFoundation() {
        //Wooden specific procedure
    }

    @Override
    void buildPillars() {
        //Wooden specific procedure
    }

    @Override
    void buildWalls() {
        //Wooden specific procedure
    }

    @Override
    void buildWindows() {
        //Wooden specific procedure
    }
}
Java
class TemplatePatternDemo {
    public static void main(String[] args) {

        House glassHouse = new GlassHouse();
        glassHouse.contructHouse();

        House woodenHouse = new WoodenHouse();
        woodenHouse.contructHouse();
    }
}

State Pattern

Image 6

Java
public interface State {
    public void doAction(Context context);
}
Java
//current environment

public class Context {
    private State state;

    public Context() {
        state = null;
    }

    public void setState(State state) {
        this.state = state;
    }

    public State getState() {
        return state;
    }
}
Java
public class StartState implements State {

    public void doAction(Context context) {
        System.out.println("Player is in start state");
        context.setState(this); //state is saved
    }

    public String toString() {
        return "Start State";
    }
}

public class StopState implements State {

    public void doAction(Context context) {
        System.out.println("Player is in stop state");
        context.setState(this); //New state is saved
    }

    public String toString() {
        return "Stop State";
    }
}
Java
public class StatePatternDemo {
    public static void main(String[] args) {
        Context context = new Context();

        StartState startState = new StartState();
        startState.doAction(context); //state will be changed within
        System.out.println(context.getState().toString());

        StopState stopState = new StopState();
        stopState.doAction(context); //state will be changed within
        System.out.println(context.getState().toString());
    }
}

Obeserver Pattern

Image 7

Java
interface Subject {
    void registerObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObservers();
}
Java
class Product implements Subject {
    private ArrayList<Observer> observers = new ArrayList<Observer>();
    private String productName;
    String availability;

    public Product(String productName, String productType, String availability) {
        super();
        this.productName = productName;
        this.availability = availability;
    }
    public ArrayList<Observer> getObservers() {
        return observers;
    }
    public void setObservers(ArrayList<Observer> observers) {
        this.observers = observers;
    }
}
Java
 public String getProductName() {
        return productName;
    }
    public void setProductName(String productName) {
        this.productName = productName;
    }
    public String getAvailability() {
        return availability;
    }
    public void setAvailability(String availability) {
        this.availability = availability;
        notifyObservers();
    }

    public void notifyObservers() {
        System.out.println("Notifying to all the subscribers when product became available");
        for (Observer ob : observers) {
            ob.update(this.availability);
        }
    }
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
}
Java
interface Observer {
    void update(String availability);
}
Java
class Person implements Observer {

    String personName;

    public Person(String personName) {
        this.personName = personName;
    }

    public String getPersonName() {
        return personName;
    }

    public void setPersonName(String personName) {
        this.personName = personName;
    }

    public void update(String availabiliy) {

        System.out.println("Hello " + personName + ", 
        Product is now " + availabiliy + " on flipkart");
    }
}
Java
class ObserverPatternMain {

    public static void main(String[] args) {
        Person arpitPerson = new Person("Arpit");
        Person johnPerson = new Person("John");

        Product samsungMobile = new Product("Samsung", "Mobile", "Not available");

        //When you opt for option "Notify me when product is available".
        samsungMobile.registerObserver(arpitPerson);
        samsungMobile.registerObserver(johnPerson);

        //Now product is available 
        samsungMobile.setAvailability("Available");
    }
}

Facade Pattern

Image 8

Java
class CPU {

    public void freeze() {...}

    public void jump(long position) {...}

    public void execute() {...}
}

class Memory {
    public void load(long position, byte[] data) {...}
}

class HardDrive {
    public byte[] read(long lba, int size) {...}
}
Java
class ComputerFacade {
    private CPU processor;
    private Memory ram;
    private HardDrive hd;

    public ComputerFacade() {
        this.processor = new CPU();
        this.ram = new Memory();
        this.hd = new HardDrive();
    }

    public void start() {
        processor.freeze();
        ram.load(BOOT_ADDRESS, hd.read(BOOT_SECTOR, SECTOR_SIZE));
        processor.jump(BOOT_ADDRESS);
        processor.execute();
    }
}
Java
class You {
    public static void main(String[] args) {

        //User does not need to know complex logic

        ComputerFacade computer = new ComputerFacade();
        computer.start();
    }
}

Proxy Pattern

Image 9

Another Example

Image 10

Java
public interface Image {
    void display();
}
Java
public class RealImage implements Image {

    private String fileName;

    public RealImage(String fileName){
        this.fileName = fileName;
        loadFromDisk(fileName);
    }

    @Override
    public void display() {
        System.out.println("Displaying " + fileName);
    }

    private void loadFromDisk(String fileName){
        System.out.println("Loading " + fileName);
    }
}
Java
public class ProxyImage implements Image{

    private RealImage realImage;
    private String fileName;

    public ProxyImage(String fileName){
        this.fileName = fileName;
    }

    @Override
    public void display() {
        if(realImage == null){
            realImage = new RealImage(fileName);
        }
        realImage.display();
    }
}
Java
public class ProxyPatternDemo {

    public static void main(String[] args) {
        Image image = new ProxyImage("test_10mb.jpg");

        //image will be loaded from disk
        image.display();
        System.out.println("");

        //image will not be loaded from disk
        image.display();
    }
}

Decorator Pattern

Image 11

Another Example

Image 12

Java
interface Car {
    public void manufactureCarBody();
}

class BMWCar implements Car {
    private String engine;

    public String getEngine() {
        return engine;
    }

    public void setEngine(String engine) {
        this.engine = engine;
    }

    @Override
    public void manufactureCarBody() {
        //Procedure of manufacturing outer body
    }
}
Java
abstract class CarDecorator implements Car {
    Car car;

    public CarDecorator(Car car) {
        this.car = car;
    }

    public void manufactureCarBody() {
        car.manufactureCarBody();
    }
}
Java
class DieselCarDecorator extends CarDecorator {

    public DieselCarDecorator(Car car) {
        super(car);
    }

    public void manufactureCarBody() {
        car.manufactureCarBody();
        addEngine(car);
    }

    public void addEngine(Car car) {
        if (car instanceof BMWCar) {
            BMWCar BMWCar = (BMWCar) car;
            BMWCar.setEngine("Diesel Engine");
        }

    }
}
Java
class PetrolCarDecorator extends CarDecorator {

    public PetrolCarDecorator(Car car) {
        super(car);
    }

    public void manufactureCarBody() {
        car.manufactureCarBody();
        addEngine(car);
    }

    public void addEngine(Car car) {
        if (car instanceof BMWCar) {
            BMWCar BMWCar = (BMWCar) car;
            BMWCar.setEngine("Petrol Engine");
        }
    }
}
Java
class DecoratorClient {

    public static void main(String[] args) {
        Car bmwCar1 = new BMWCar();
        DieselCarDecorator carWithDieselEngine = new DieselCarDecorator(bmwCar1);
        carWithDieselEngine.manufactureCarBody();

        Car bmwCar2 = new BMWCar();
        PetrolCarDecorator carWithPetrolEngine = new PetrolCarDecorator(bmwCar2);
        carWithPetrolEngine.manufactureCarBody();
    }
}

MVC - Architectural Pattern

Image 13

Java
public class Student {
    private String rollNo;
    private String name;

    public String getRollNo() {
        return rollNo;
    }

    public void setRollNo(String rollNo) {
        this.rollNo = rollNo;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
Java
public class StudentView {
    public void printStudentDetails(String studentName, String studentRollNo) {
        System.out.println("Student: ");
        System.out.println("Name: " + studentName);
        System.out.println("Roll No: " + studentRollNo);
    }
}
Java
public class StudentView {
    public void printStudentDetails(String studentName, String studentRollNo) {
        System.out.println("Student: ");
        System.out.println("Name: " + studentName);
        System.out.println("Roll No: " + studentRollNo);
    }
}
Java
public class StudentController {
    private Student model;
    private StudentView view;
    public StudentController(Student model, StudentView view) {
        this.model = model;
        this.view = view;
    }
    public void setStudentName(String name) {
        model.setName(name);
    }
    public String getStudentName() {
        return model.getName();
    }
    public void setStudentRollNo(String rollNo) {
        model.setRollNo(rollNo);
    }
    public String getStudentRollNo() {
        return model.getRollNo();
    }

    //controller is bridge between model and view
    public void updateView() {
        view.printStudentDetails(model.getName(), model.getRollNo());
    }
}

More patterns are coming soon in this article... your suggestions are welcome. :)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)