Pages

Label

Rabu, 30 Januari 2019

Design Pattern in Java

Hello Guys!!! Hope you all are doing well. 
Today I am going to discuss some famous Design Pattern in Java and Android.
First  start with What is Design Pattern ?
In software engineering, a design pattern is a general repeatable solution to a commonly occurring problem in software design. A design pattern isn't a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations.
Some of the benefits of using design patterns are:
  • Design Patterns are already defined and provides industry standard approach to solve a recurring problem, so it saves time if we sensibly use the design pattern. There are many java design patterns that we can use in our java/Android based projects.
  • Using design patterns promotes reusability that leads to more robust and highly maintainable code. It helps in reducing total cost of ownership (TCO) of the software product.
  • Since design patterns are already defined, it makes our code easy to understand and debug. It leads to faster development and new members of team understand it easily.
Java Design Patterns are divided into three categories –
  •  Creational, 
  •  Structural, and 
  •  Behavioral
Creational Design Pattern
  • This is all about the class instantiation
  • Uses class creation pattern and object creation pattern
  • Class creation pattern uses inheritance effectively
  • Object cation pattern uses delegation to get the job done
Structural Design Pattern 
Describe how object and classes can be combined to form larger structures

Behavioral Design Pattern 
  • Those patterns which are specifically concerned with communication between the object.
  • The interaction between the objects should be such a way that they are talking to each other and still are loosely coupled to avoid hard coding and dependencies.
In Short we can say :- 
Creational patterns: how you create objects.
Structural patterns: how you compose objects.
Behavioral patterns: how you coordinate object interactions.

Design Pattern used in Android 

Android functionality or API Used Design Pattern
Adapter Adapter Design Pattern
Notification Builder Design Pattern
Broadcast Receiver Observer Pattern
Intent Factory Design Pattern
View Holder Singleton Design Pattern
View and View Group Composite Design Pattern
Media Framework Facade Pattern
Remote Service invocation Proxy Pattern

Top 10 design pattern example
  1. Singleton
  2. Proxy
  3. Factory Method
  4. Abstract Factory
  5. Adapter
  6. Decorator
  7. Builder
  8. Observer
Singleton pattern
  • Comes in the Creational Design Pattern category
  • Restricts the instantiation of a class and ensures that only one instance of the class exists in the java virtual machine
  • it seems to be a very simple design pattern but when it comes to implementation, it comes with a lot of implementation concerns
  • The implementation of Java Singleton pattern has always been a controversial topic among developers
Example:- Download source code 
Approaches:-
1. Eager initialization
In eager initialization, the instance of Singleton Class is created at the time of class loading, this is the easiest method to create a singleton class but it has a drawback that instance is created even though client application might not be using it.
package com.sks.singleton.example;
public class EagerInitializedSingleton {
    private static final EagerInitializedSingleton instance = new EagerInitializedSingleton();
    // private constructor to avoid client applications to use constructor
    private EagerInitializedSingleton() {
    }

    public static EagerInitializedSingleton getInstance() {
        return instance;
    }
}
2. Lazy initialization
it restricts the creation of instance until requested first time. Lets see in code:
package com.sks.singleton.example;
public class LazySingleton {
    /*
     *Please ensure to use “volatile” keyword with instance variable 
     *otherwise you can run into out of order write error scenario, 
     *where reference of instance is returned before actually the object is constructed 
     *i.e. JVM has only allocated the memory and constructor code is still not executed. 
     *In this case, your other thread, which refer to uninitialized object may throw null pointer exception
     * and can even crash the whole application
     */
    private static volatile LazySingleton instance = null;

    // private constructor
    private LazySingleton() {
    }
    public static LazySingleton getInstance() {
        if (instance == null) {
            synchronized (LazySingleton.class) {
                instance = new LazySingleton();
            }
        }
        return instance;
    }
}
But, this method also has its own drawbacks. Lets see how.
Suppose there are two threads T1 and T2. Both comes to create instance and execute “instance==null”, now both threads have identified instance variable to null thus assume they must create an instance. They sequentially goes to synchronized block and create the instances. At the end, we have two instances in our application.

This error can be solved using double-checked locking. This principle tells us to recheck the instance variable again in synchronized block in given below way:
    //Double lock checking...
    public static LazySingleton getInstance() {
        if (instance == null) {
            synchronized (LazySingleton.class) {
                // Double check
                if (instance == null) {
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }
3. Bill pugh solution
Bill pugh was main force behind java memory model changes. He suggested to use static inner class.
package com.sks.singleton.example;
public class BillPughSingleton {

    private BillPughSingleton() {
    }
    private static class LazyHolder {
        private static final BillPughSingleton INSTANCE = new BillPughSingleton();
    }
    public static BillPughSingleton getInstance() {
        return LazyHolder.INSTANCE;
    }
}
As you can see, until we need an instance, the LazyHolder class will not be initialized until required and you can still use other static members of BillPughSingleton class. 
This is the solution, I will recommend to use. I also use it in my all projects.
4. Adding readResolve()
  • By Seeing above example, hopefully you have taken your decision that how you would like to implement your singleton.
  • Now lets see other problems that may arise due to serialization and de-serialization (always creates a new instance).
  • To solve this issue, we need to include readResolve() method in our DemoSingleton class. This method will be invoked when you will de-serialize the object. 
  • Inside this method, you must return the existing instance to ensure single instance application wide.
package com.sks.singleton.example;
import java.io.Serializable;
public class DemoSingleton implements Serializable {
    private static final long serialVersionUID = 1L;

    private DemoSingleton() {
        // private constructor
    }

    private static class DemoSingletonHolder {
        public static final DemoSingleton INSTANCE = new DemoSingleton();
    }

    public static DemoSingleton getInstance() {
        return DemoSingletonHolder.INSTANCE;
    }

    protected Object readResolve() {
        return getInstance();
    }
}
2. Proxy Design Pattern 
Provide a surrogate or placeholder for another object to control access to it.
Proxy is applicable whenever there is a need for a more versatile or sophisticated reference to an object than a simple pointer.
common situations in which the Proxy pattern is applicable :-

  • Remote proxy provides a local representative for an object in a different address space.
  • Virtual proxy creates expensive objects on demand.
  • Protection proxy controls access to the original object. Protection proxies are useful when objects should have different access rights.

Typical Use Case
  • Control access to another object
  • Lazy initialization
  • Implement logging
  • Facilitate network connection
  • Count references to an object

Implementation Diagram for proxy


3. Factory Method
The Factory Design Pattern is probably the most used design pattern in modern programming languages. Factory Design pattern is based on Encapsulation object oriented concept. There are different variants and implementations.
Here We discuss two variant:-

  • Factory Method and 
  • Abstract Factory
Factory method is used to create different object from factory often refereed as Item and it encapsulate the creation code. So instead of having object creation code on client side we encapsulate inside Factory method in Java.
package com.sks.factory.example;
public interface Coffee {

    String getCoffeeVariant();
}

package com.sks.factory.example;
public class Cappuccino implements Coffee{

    @Override
    public String getCoffeeVariant() {

        return "Cappuccino...";
    }
}

package com.sks.factory.example;
public class FreshCoffee implements Coffee{

    @Override
    public String getCoffeeVariant() {

        return "Fresh Coffee";
    }
}

package com.sks.factory.example;
public class VienneseCoffee implements Coffee{

    @Override
    public String getCoffeeVariant() {

        return "Viennese Coffee...";
    }
}

package com.sks.factory.example;
public class CoffeeFactory {

    public static Coffee getCoffeeVariant(String Coffee) {
           if (Coffee.equalsIgnoreCase ("Fresh")){
                  return new FreshCoffee();
           }else if(Coffee.equalsIgnoreCase ("Cappuccino")){
                  return new Cappuccino();
           }else if(Coffee.equalsIgnoreCase ("Viennese")){
                  return new VienneseCoffee();
            }
           throw new IllegalArgumentException("No such Coffee");
    }
}

package com.sks.factory.example;
import java.util.Scanner;
public class Factoryclient {

    public static void main(String[] args) {
        String coffee = "test";
        System.out.println("Enter Coffee name.\n");
        Scanner mscan = new Scanner(System.in);
        try {
            coffee = mscan.nextLine();
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        mscan.close();

        Coffee mCoffee = CoffeeFactory.getCoffeeVariant(coffee);
        System.out.println(mCoffee.getCoffeeVariant());
    }
}
When to use Factory design pattern
  • Static Factory methods are common in frameworks where library code needs to create objects of types which may be sub classed by applications using the framework. 
  • Some or all concrete products can be created in multiple ways, or we want to leave open the option that in the future there may be new ways to create the concrete product.
  • Factory method is used when Products don't need to know how they are created.
  • We can use factory pattern where we have to create an object of any one of sub-classes depending on the data provided

4. Abstract Factory Pattern
Define an interface or abstract class for creating families of related (or dependent) objects but without specifying their concrete sub-classes.
That means Abstract Factory lets a class returns a factory of classes. This is why? Abstract Factory Pattern is one level higher than the Factory Pattern.
An Abstract Factory Pattern is also known as Kit.
Advantage
  • Isolates the client code from concrete (implementation) classes.
  • It eases the exchanging of object families.
  • It promotes consistency among objects.
Usage
  • when System needs to be independent of how its object are created, composed, and represented.
  • When the family of related objects has to be used together, then this constraint needs to be enforced.
  • When you want to provide a library of objects that does not show implementations and only reveals interfaces.
  • When the system needs to be configured with one of a multiple family of objects.

package com.sks.abstractfactory.example;
public interface Fruits {

    public String getFruitsName();
    public String getFruitType();
}
package com.sks.abstractfactory.example;
public interface FruitsFactory {

    public Fruits getFruitDetail();
}
package com.sks.abstractfactory.example;
public class ConsumeFruitFactory {

    public ConsumeFruitFactory(FruitsFactory fruitFactory) {
        if(fruitFactory != null) {
        Fruits mfruit = fruitFactory.getFruitDetail();
            System.out.println(mfruit.getFruitsName());
            System.out.println(mfruit.getFruitType());  
        }else {
            System.out.println("No such a Fruit. Please add it.");
        }

    }
}
package com.sks.abstractfactory.example;
public class AbstractFactoryClient {

    public static void main(String[] args) {

        new ConsumeFruitFactory(getFruitDetail("Orange"));
    }

    public static FruitsFactory getFruitDetail(String type) {
        if("Orange".equalsIgnoreCase(type)) {
            return new OrangeFactory();
        }else if("Mango".equalsIgnoreCase(type)) {
            return new MangoFactory();
        }else if("Apple".equalsIgnoreCase(type)) {
            return new AppleFactory();
        }else {
            return null;
        }
    }
}
package com.sks.abstractfactory.example;
public class Apple implements Fruits {

    @Override
    public String getFruitsName() {

        return "Apple";
    }

    @Override
    public String getFruitType() {

        return "An apple a day";
    }
}
5. Adapter
Definition:- 
An adapter pattern helps two incompatible interfaces to work together.
The adapter design pattern is used when you want two different classes with incompatible interfaces to work together.
The Adapter Pattern is also known as Wrapper.
Advantage
  • By using Adapter design pattern two or more previously incompatible objects to interact.
  • Adapter design pattern allows reusability of existing functionality.

Implementation 

Adapter design pattern can be implemented in two ways.

  1. using the inheritance method and 
  2. using the composition method
Just the implementation methodology is different but the purpose and solution is same.
package com.sks.adapter.example;
public interface Flower {

    // Flowers implement Flower interface that allows
    // them to blossom and to spread Aroma in adaptee interface
    public void blossom();
    public void aroma();
}
package com.sks.adapter.example;
public class FlowerAdapter implements ToyFlower{
      // You need to implement the interface your
    // client expects to use.
    Flower flower;

    public FlowerAdapter(Flower flower){
        this.flower = flower;
    }

    @Override
    public void beautiful() {
        System.out.println("Real Flower Beautiful via Adapter");
    }
}
package com.sks.adapter.example;
public interface ToyFlower {

    // target interface
    // ToyFlower don't blossom and have no aroma they just
    // look beautiful like real flower.
    public void beautiful();
}
6.Decorator

  • Decorator design pattern is used to enhance the functionality of a particular object at run-time or dynamically.
  • At the same time other instance of same class will not be affected by this so individual object gets the new behavior.
  • Basically we wrap the original object through decorator object.
  • Decorator design pattern is based on abstract classes and we derive concrete implementation from that classes,
  • It’s a structural design pattern and most widely used.

package com.sks.decorator.example;
public interface Food {

    public String prepareFood();  
    public double foodPrice();  
}
package com.sks.decorator.example;
/*
 * FoodDecorator abstract class implements the Food interface and override it's all methods 
 * and it has the ability to decorate some more foods.*/
public abstract class FoodDecorator implements Food {

    private Food newFood;

    public FoodDecorator(Food newFood) {
        this.newFood = newFood;
    }

    @Override
    public String prepareFood() {
        return newFood.prepareFood();
    }

    public double foodPrice() {
        return newFood.foodPrice();
    }
}
package com.sks.decorator.example;
public class VegFood implements Food{

    @Override
    public String prepareFood() {

        return "Veg Food";
    }

    @Override
    public double foodPrice() {

        return 50.0;
    }
}

package com.sks.decorator.example;
/*
 * NonVegFood concrete class that will extend the FoodDecorator class and override it's all methods
 */
public class NonVegFood extends FoodDecorator {

    public NonVegFood(Food newFood) {
        super(newFood);

    }

    public String prepareFood() {
        return super.prepareFood() + " With Roasted Chiken and Chiken Curry  ";
    }

    public double foodPrice() {
        return super.foodPrice() + 150.0;
    }

package com.sks.decorator.example;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class DecoratorPatternClient {
    private static int choice;

    public static void main(String[] args) throws NumberFormatException, IOException {
        do {
            System.out.print("========= Food Menu ============ \n");
            System.out.print("            1. Vegetarian Food.   \n");
            System.out.print("            2. Non-Vegetarian Food.\n");
            System.out.print("            3. Chineese Food.         \n");
            System.out.print("            4. Exit                        \n");
            System.out.print("Enter your choice: ");
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            choice = Integer.parseInt(br.readLine());
            switch (choice) {
            case 1: {
                VegFood vf = new VegFood();
                System.out.println(vf.prepareFood());
                System.out.println(vf.foodPrice());
            }
                break;

            case 2: {
                Food f1 = new NonVegFood((Food) new VegFood());
                System.out.println(f1.prepareFood());
                System.out.println(f1.foodPrice());
            }
                break;
            case 3: {
                Food f2 = new ChineeseFood((Food) new VegFood());
                System.out.println(f2.prepareFood());
                System.out.println(f2.foodPrice());
            }
                break;

            default: {
                System.out.println("Other than these no food available");
            }
                return;
            }// end of switch

        } while (choice != 4);

    }
}
7. Builder Design Pattern 
....continue.... 

0 komentar:

Posting Komentar

 
[tutup]