Design Pattern

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 15

Design Pattern - Singleton Pattern

Singleton pattern is one of the simplest design patterns in Java. This type of design
pattern comes under creational pattern as this pattern provides one of the best ways
to create an object.
This pattern involves a single class which is responsible to create an object while
making sure that only single object gets created. This class provides a way to access
its only object which can be accessed directly without need to instantiate the object
of the class.

Implementation
We're going to create a SingleObject class. SingleObject class have its constructor
as private and have a static instance of itself.
SingleObject class provides a static method to get its static instance to outside
world. SingletonPatternDemo, our demo class will use SingleObject class to get
a SingleObject object.

Step 1
Create a Singleton Class.
SingleObject.java
public class SingleObject {

//create an object of SingleObject


private static SingleObject instance = new SingleObject();

//make the constructor private so that this class cannot be


//instantiated
private SingleObject(){}

//Get the only object available


public static SingleObject getInstance(){
return instance;
}

public void showMessage(){


System.out.println("Hello World!");
}
}

Step 2
Get the only object from the singleton class.
SingletonPatternDemo.java
public class SingletonPatternDemo {
public static void main(String[] args) {

//illegal construct
//Compile Time Error: The constructor SingleObject() is not visible
//SingleObject object = new SingleObject();

//Get the only object available


SingleObject object = SingleObject.getInstance();

//show the message


object.showMessage();
}
}

Step 3
Verify the output.

Design Patterns - Adapter Pattern


Adapter pattern works as a bridge between two incompatible interfaces. This type of
design pattern comes under structural pattern as this pattern combines the capability
of two independent interfaces.
This pattern involves a single class which is responsible to join functionalities of
independent or incompatible interfaces. A real life example could be a case of card
reader which acts as an adapter between memory card and a laptop. You plugin the
memory card into card reader and card reader into the laptop so that memory card
can be read via laptop.
We are demonstrating use of Adapter pattern via following example in which an
audio player device can play mp3 files only and wants to use an advanced audio
player capable of playing vlc and mp4 files.

Implementation
We have a MediaPlayer interface and a concrete class AudioPlayer implementing
the MediaPlayer interface. AudioPlayer can play mp3 format audio files by default.
We are having another interface AdvancedMediaPlayer and concrete classes
implementing the AdvancedMediaPlayer interface. These classes can play vlc and
mp4 format files.
We want to make AudioPlayer to play other formats as well. To attain this, we have
created an adapter class MediaAdapter which implements the MediaPlayer interface
and uses AdvancedMediaPlayer objects to play the required format.
AudioPlayer uses the adapter class MediaAdapter passing it the desired audio type
without knowing the actual class which can play the desired
format. AdapterPatternDemo, our demo class will use AudioPlayer class to play
various formats.

Step 1
Create interfaces for Media Player and Advanced Media Player.
MediaPlayer.java
public interface MediaPlayer {
public void play(String audioType, String fileName);
}
AdvancedMediaPlayer.java
public interface AdvancedMediaPlayer {
public void playVlc(String fileName);
public void playMp4(String fileName);
}

Step 2
Create concrete classes implementing the AdvancedMediaPlayer interface.
VlcPlayer.java
public class VlcPlayer implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
System.out.println("Playing vlc file. Name: "+ fileName);
}

@Override
public void playMp4(String fileName) {
//do nothing
}
}
Mp4Player.java
public class Mp4Player implements AdvancedMediaPlayer{

@Override
public void playVlc(String fileName) {
//do nothing
}

@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file. Name: "+ fileName);
}
}

Step 3
Create adapter class implementing the MediaPlayer interface.
MediaAdapter.java
public class MediaAdapter implements MediaPlayer {

AdvancedMediaPlayer advancedMusicPlayer;

public MediaAdapter(String audioType){

if(audioType.equalsIgnoreCase("vlc") ){
advancedMusicPlayer = new VlcPlayer();
}else if (audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer = new Mp4Player();
}
}

@Override
public void play(String audioType, String fileName) {

if(audioType.equalsIgnoreCase("vlc")){
advancedMusicPlayer.playVlc(fileName);
}
else if(audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer.playMp4(fileName);
}
}
}

Step 4
Create concrete class implementing the MediaPlayer interface.
AudioPlayer.java
public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;

@Override
public void play(String audioType, String fileName) {

//inbuilt support to play mp3 music files


if(audioType.equalsIgnoreCase("mp3")){
System.out.println("Playing mp3 file. Name: " + fileName);
}

//mediaAdapter is providing support to play other file formats


else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
}

else{
System.out.println("Invalid media. " + audioType + " format not supported");
}
}
}

Step 5
Use the AudioPlayer to play different types of audio formats.
AdapterPatternDemo.java
public class AdapterPatternDemo {
public static void main(String[] args) {
AudioPlayer audioPlayer = new AudioPlayer();

audioPlayer.play("mp3", "beyond the horizon.mp3");


audioPlayer.play("mp4", "alone.mp4");
audioPlayer.play("vlc", "far far away.vlc");
audioPlayer.play("avi", "mind me.avi");
}
}

Step 6
Verify the output.
Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name: alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media. avi format not supported

Design Patterns - Iterator Pattern


Iterator pattern is very commonly used design pattern in Java and .Net programming
environment. This pattern is used to get a way to access the elements of a collection
object in sequential manner without any need to know its underlying representation.
Iterator pattern falls under behavioral pattern category.

Implementation
We're going to create a Iterator interface which narrates navigation method and
a Container interface which retruns the iterator . Concrete classes implementing
the Container interface will be responsible to implement Iterator interface and use it
IteratorPatternDemo, our demo class will use NamesRepository, a concrete class
implementation to print a Names stored as a collection in NamesRepository.
Step 1
Create interfaces.
Iterator.java
public interface Iterator {
public boolean hasNext();
public Object next();
}
Container.java
public interface Container {
public Iterator getIterator();
}

Step 2
Create concrete class implementing the Container interface. This class has inner
class NameIterator implementing the Iterator interface.
NameRepository.java
public class NameRepository implements Container {
public String names[] = {"Robert" , "John" ,"Julie" , "Lora"};

@Override
public Iterator getIterator() {
return new NameIterator();
}

private class NameIterator implements Iterator {

int index;

@Override
public boolean hasNext() {

if(index < names.length){


return true;
}
return false;
}

@Override
public Object next() {

if(this.hasNext()){
return names[index++];
}
return null;
}
}
}

Step 3
Use the NameRepository to get iterator and print names.
IteratorPatternDemo.java
public class IteratorPatternDemo {

public static void main(String[] args) {


NameRepository namesRepository = new NameRepository();

for(Iterator iter = namesRepository.getIterator(); iter.hasNext();){


String name = (String)iter.next();
System.out.println("Name : " + name);
}
}
}

Step 4
Verify the output.
Name : Robert
Name : John
Name : Julie
Name : Lora

Design Patterns - Observer Pattern


Observer pattern is used when there is one-to-many relationship between objects
such as if one object is modified, its depenedent objects are to be notified
automatically. Observer pattern falls under behavioral pattern category.

Implementation
Observer pattern uses three actor classes. Subject, Observer and Client. Subject is
an object having methods to attach and detach observers to a client object. We have
created an abstract class Observer and a concrete class Subject that is extending
class Observer.
ObserverPatternDemo, our demo class, will use Subject and concrete class object to
show observer pattern in action.
Step 1
Create Subject class.
Subject.java
import java.util.ArrayList;
import java.util.List;

public class Subject {

private List<Observer> observers = new ArrayList<Observer>();


private int state;

public int getState() {


return state;
}

public void setState(int state) {


this.state = state;
notifyAllObservers();
}

public void attach(Observer observer){


observers.add(observer);
}

public void notifyAllObservers(){


for (Observer observer : observers) {
observer.update();
}
}
}

Step 2
Create Observer class.
Observer.java
public abstract class Observer {
protected Subject subject;
public abstract void update();
}

Step 3
Create concrete observer classes
BinaryObserver.java
public class BinaryObserver extends Observer{

public BinaryObserver(Subject subject){


this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) );
}
}
OctalObserver.java
public class OctalObserver extends Observer{

public OctalObserver(Subject subject){


this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
System.out.println( "Octal String: " + Integer.toOctalString( subject.getState() ) );
}
}
HexaObserver.java
public class HexaObserver extends Observer{

public HexaObserver(Subject subject){


this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
System.out.println( "Hex String: " + Integer.toHexString( subject.getState() ).toUpperCase()
);
}
}

Step 4
Use Subject and concrete observer objects.
ObserverPatternDemo.java
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();

new HexaObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);

System.out.println("First state change: 15");


subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}

Step 5
Verify the output.
First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010

Multiton Design Pattern

Multiton is a creational design pattern. You can assume it as an extension of singleton


design pattern. Rather than having a single instance per application, multiton pattern
instead ensures a single instance per key.
Let’s say there is a student database, where each student mapped to exactly one
address. We can do the implementation using multiton design pattern.

Address.java

public class Address {


private String street;
private String city;
private String district;
private String state;
private String country;
private String PIN;

public String getPIN() {


return PIN;
}

public String getCity() {


return city;
}

public String getCountry() {


return country;
}

public String getDistrict() {


return district;
}

public String getState() {


return state;
}

public String getStreet() {


return street;
}

public void setPIN(String PIN) {


this.PIN = PIN;
}

public void setCity(String city) {


this.city = city;
}

public void setCountry(String country) {


this.country = country;
}

public void setDistrict(String district) {


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

public void setStreet(String street) {


this.street = street;
}
}

Student.java

public class Student {


private String firstName;
private String lastName;
private int age;
private int id;

public int getAge() {


return age;
}

public String getFirstName() {


return firstName;
}

public int getId() {


return id;
}

public String getLastName() {


return lastName;
}

public void setAge(int age) {


this.age = age;
}

public void setFirstName(String firstName) {


this.firstName = firstName;
}

public void setId(int id) {


this.id = id;
}

public void setLastName(String lastName) {


this.lastName = lastName;
}
}

StudentDatabase.java
import java.util.Map;
import java.util.HashMap;

public class StudentDatabase {


private static Map<Student, Address> studentDb = new HashMap<Student,
Address> ();

/* Get the Address associated with student */


public static Address getStudentAddress(Student s){
/* Check whether student exist in database or not */
if(studentDb.containsKey(s)){
Address addr;
addr = studentDb.get(s);

/* If address not exist for this student, create address


instance and map it to student */
if(addr == null){
addr = new Address();
studentDb.put(s, addr);
}
return addr;
}
return null;
}

public static Map<Student, Address> getStudentDb() {


return studentDb;
}

public static void setStudentDb(Map<Student, Address> studentDb) {


StudentDatabase.studentDb = studentDb;
}
}

MultitonPattern.java
import java.util.HashMap;
import java.util.Map;

public class MultitonPattern {


public static void main(String args[]){
Map<Student, Address> studentDb = new HashMap<Student, Address> ();

Student s1 = new Student();


Address a1 = null;

s1.setFirstName("Krishna");
s1.setLastName("Gurram");

studentDb.put(s1, a1);

StudentDatabase.setStudentDb(studentDb);

Address addr = StudentDatabase.getStudentAddress(s1);


addr.setCity("Ongole");
addr.setCountry("India");
addr = StudentDatabase.getStudentAddress(s1);

System.out.println(addr.getCity());
System.out.println(addr.getCountry());

}
}

Output
Ongole
India

You might also like