Java Design Pattern Interview Questions
Java Design Pattern Interview Questions
With design patterns, you get to easily solve commonly recurring issues
without investing a lot of time and effort into the same. So, if your job entails
this process and you have an interview in tow, this post covers the latest
design patterns interview questions that you can refer to for preparation.
Freshers
Experienced
principles?
Do you want to enhance your skills and build your career in this Core Java domain? Then e
" Core Java Training " this course will help you to achieve excellence in this domain.
If you are just starting out in this domain, these design patterns interview questions
for freshers will be helpful in your preparation.
Design patterns are known as reusable solutions that help solve commonly
recurring issues of software development. Some of these issues are
redundant logic and functions, repetitive code, and more. These patterns
help save a significant amount of time and effort needed when developing
software. Also, these patterns are used commonly in object-oriented software
products.
Define the name of the pattern and the classification of the design
pattern under which it will fall
Define an issue and the corresponding solution
Finding the variations and language-dependent alternatives for the
issue that has to be addressed
Defining the real-time use cases along with the software’s efficiency.
In Java, there are three varying types of design patterns, such as:
structures of objects and classes should look like for defining the
are proxy design, decorator design, facade design, adaptor design, and
more.
Check out Core Java Interview Questions and Answers that help you grab high-p
jobs.
Gang of Four (GOF) is used for four authors who invented the concept of
design patterns. They are John Vlissides, Richard Hel, Ralph Johnson, and
Erich Gamma. They documented the design patterns in the book named
“Design Patterns: Elements of Reusable Object-Oriented Software”, which
was published in 1995.
for one functionality. And, there should be only one reason to change
any class.
class is open for extension and closed for modification. Here, you can
Some of the design patterns used in the JDK library of Java are:
Design patterns are known as the reusable template solutions used for
common issues that can be customized as per the requirements. These can
be implemented efficiently, are safe to use and can be tested properly.
On the other hand, design principles are followed when designing software
systems for any sort of platform by using a programming language. The
SOLID principles are the design principles that are followed as guidelines to
develop extensive, scalable, and robust software systems. These principles
can be applied to every aspect of programming.
The bridge pattern is a structural design pattern type that allows you to split
closely related classes or large classes into two hierarchies - implementation
and abstraction. These two are independent of one another and can be used
whenever you wish to decouple an abstraction from implementation.
Abstraction: This is the code and defines the crux of the pattern. It
implementers.
Implementer: This is referred to as the implementation classes’
interface.
If you are a professional and have spent years working in this domain, these
design patterns interview questions for professionals will help you prepare
thoroughly.
Inversion of Control (IoC) is one such pattern that is used to decouple the
dependencies between the system’s components and layers. The
Dependency-Injection (DI) pattern is one such example of this IoC pattern
that assists in eradicating the dependencies in the entire code.
Let’s dive deeper with an example. Suppose we have a class Y that uses class
Z as:
public class Y{
private Z z;
public Y ( ) {
this.z = new Z ( ) ;
}
}
Here, we get a dependency between the Y and Z classes. If the IoC pattern
was implemented, the new operator wouldn’t have been used to assign value
to the dependent variable. And then, it would have been:
public class Y {
private IocZ z;
public Y (IocZ z) {
this.z = z;
}
}
Factory design pattern comes under the Creational Design Patterns category.
Herein, the objects get created without exposing the creation logic to the
client. The objects are referred to the common interface.
Suppose there are three classes - Square, Rectangle, and Triangle. Let’s use
factory patterns to create objects of these classes without bringing forth the
creation logic by using the ShapeFactory class. Now, the Driver class will be
used to pass the information to get the required object.
//Shape.java
public interface Shape {
void draw();
}
//ShapeFactory.java
public class ShapeFactory {
//the method will be used to get object of required shape
public shape getShapeInstance (String type) {
if (type == null) {
return null;
}
if (type.equalsIgnoreCase (“TRIANGLE”) ) {
return new Triangle ( ) ;
} else if (type.equalsIgnoreCase (“SQUARE”) ) {
return new Square ( ) ;
} else if (type.equalsIgnoreCase (“RECTANGLE”) ) {
return new Rectangle ( ) ;
}
return null;
}
}
Step 4: Implementation of the Drive Class and Using the Factory Class
to Get the Required Object
//Driver.java
public class Driver {
public static void main (String [ ] args) {
ShapeFactory shapeFactory = new ShapeFactory ( ) ;
//get Triangle object and call draw ( )
Shape triangle = shapeFactory.getShape (“Triangle”) ;
triangle.draw ( ) ;
//get Rectangle object and call draw ( )
Shape rectangle = shapeFactory.getShape (“Rectangle”) ;
rectangle.draw ( ) ;
//get Square object and call draw ( )
Shape square = shapeFactory.getShape (“Square”) ;
square.draw ( ) ;
}
}
Triangle Drawn
Rectangle Drawn
Square Drawn
This adapter class comes with a client class and an adaptee class. While the
former expects an object type, the latter provides the same feature by
exposing a distinct interface. Now, to establish communication between the
two, there is an adapter class.
The client uses the target interface to request the adapter. And then, the
adapter class translates the request through the adaptee interface. The
client, then, receives the results without having any idea of the role of an
adapter.
To get deeper into this concept, let’s consider another example. Suppose you
have a MediaPlayer Interface that is implemented by the AudioPlayer class.
The AudioPlayer can play the format of mp3 by default. Let’s consider
another interface, which is AdvancedPlayer, implemented by the MP4Player
class that plays the mp4 formats. And then, there is a WAVPlayer that plays
wav formats.
If you want the AudioPlayer class to play different formats, you will have to
use the MediaAdapter class that implements the MediaPlayer interface and
makes use of the AdvancedPlayer objects to play the needed format.
//MediaPlayer.java
public interface MediaPlayer {
public void play (String format, String file) ;
}
//AdvancedPlayer.java
public interface AdvancedPlayer {
public void playMP4 (String file) ;
public void playWav (String file) ;
}
//MP4Player.java
public class Mp4Player implements AdvancedPlayer{
@Override
public void playMp4 (String file) {
System.out.printIn (“MP4 File “ + file + “ Playing….”) ;
}
@Override
public void playWav (String file) {
//do nothing
}
}
//WAVPlayer.java
public class WAVPlayer implements AdvancedPlayer{
@Override
public void playMP4 (String file) {
//do nothing
}
@Override
public void playWav (String fille) {
System.out.printIn (“WAV File “ + file + “ Playing….”) ;
}
}
//MediaAdapter.java
public class MediaAdapter implements MediaPlayer {
AdvancedPlayer advancedPlayer;
public MediaAdapter(String format){
if(format.equalsIgnoreCase("mp4") ){
advancedPlayer = new Mp4Player();
}else if(format.equalsIgnoreCase("wav") ){
advancedPlayer = new WAVPlayer();
}
}
@Override
public void play(String format, String file) {
if(format.equalsIgnoreCase("mp4")){
advancedPlayer.playMp4(file);
}
else if(format.equalsIgnoreCase("wav")){
advancedPlayer.playWav(file);
}
}
}
//AudioPlayer.java
public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;
@Override
public void play(String format, String file) {
//inbuilt support to play mp3 music files
if(format.equalsIgnoreCase("mp3")){
System.out.println("MP3 file " + file +" Playing...");
}
//Make use of Adapter to support different formats
else if(format.equalsIgnoreCase("wav") ||
format.equalsIgnoreCase("mp4")){
mediaAdapter = new MediaAdapter(format);
mediaAdapter.play(format, file);
}
else{
System.out.println("Format not supported");
}
}
}
//Driver.java
public class Driver {
public static void main(String[] args) {
AudioPlayer audioPlayer = new AudioPlayer();
audioPlayer.play("mp3", "music1.mp3");
audioPlayer.play("wav", "music2.wav");
audioPlayer.play("mp4", "music3.mp4");
audioPlayer.play("avi", "music4.avi");
}
}
// Shape.java
public interface Shape {
void draw ( ) ;
}
// Rectangle.java
public class Rectangle implements Shape {
// Overriding the draw method
@Override public void draw ( )
{
System.out.printIn (“Rectangle Drawn…”) ;
}
}
// Triangle.java
public class Triangle implements Shape {
// Overriding the draw method
@Override public void draw ( )
{
System.out.printIn (“Triangle Drawn…”) ;
}
}
// ShapeDecorator.java
public abstract class ShapeDecorator implements Shape {
protected Shape shapeDecorated;
public ShapeDecorator (Shape shapeDecorated)
{
this.shapeDecorated = shapeDecorated;
}
public void draw ( ) {
shapeDecorated.draw ( ) ;
}
}
// Driver.java
public class Driver {
// Main driver method
public static void main (String [ ] argos)
{
Shape triangle = new Triangle ( ) ;
Shape redTriangle
= new RedColorDecorator (new Triangle ( ) ) ;
Shape redRectangle = new RedColorDecorator (new
Rectangle ( ) ) ;
// Draw normal triangle
triangle.draw ( ) ;
System.out.printIn (“.........”) ;
// make the triangle red
redTriangle.draw ( ) ;
System.out.printIn (“.........”) ;
// make the rectangle red
redRectangle.draw ( ) ;
System.out.printIn (“..........”) ;
}
}
Triangle Drawn...
.........
Triangle Drawn...
Red color border added...
.........
Rectangle Drawn...
Red color border added...
.........
The command pattern is the type of behavioral design pattern that helps
transform a request into a stand-alone object that comprises all of the details
about that request. This one is a data-driven pattern as we use the
information regarding the request by wrapping the same as an object, which
is then passed to the invoker object in the form of a command.
The invoker object looks for the object that can manage the command and
passes it to the object for the command execution. There is a client that calls
the invoker to run the command. There is a command interface that acts as
an abstraction to the concrete classes.
Let’s understand it with an example of remote control that only has one
button. Through this button, you can control the behavior of two objects -
tubelight and a radio. Thus, the command design pattern will be used to
command the handling of objects.
// Command Interface
interface Command
{
public void execute ( ) ;
}
// Tubelight class
class TubeLight
{
public void lightOn ( ) {
System.out.printIn (“TubeLight on…”) ;
}
public void lightOff ( ) {
System.out.printIn (“TubeLight off…”) ;
}
}
// Command class to turn on the tubelight
class TubeLightOnCommand implements Command
{
TubeLight tubeLight ;
// The constructor is passed the light it
// is going to control.
public TubeLightOnCommand (Tubelight tubeLight) {
this.tubeLight = tubeLight ;
}
public void execute ( ) {
tubeLight.lightOn ( ) ;
}
}
// Command class to turn off the tubelight
class TubeLightOffCommand implements Command
{
TubeLight tubeLight ;
public TubeLightOffCommand (TubeLight tubeLight) {
this.tubeLight = tubeLight ;
}
public void execute ( ) {
tubeLight.lightOff ( ) ;
}
}
// Radio class
class Radio
{
public void radioOn ( )
{
System.out.printIn (“Radio on…”) ;
}
public void radioOff ( )
{
System.out.prinIn (“Radio off…”) ;
}
public void setVolume (int volumeLevel)
{
// code to set the volume
System.out.printIn (“Radio volume set to “ +
volumeLevel) ;
}
}
// Command class to turn on the radio
class RadioOnCommand implements Command
{
Radio radio;
public RadioOnCommand (Radio radio)
{
this.radio = radio;
}
public void execute ( )
{
radio.radioOn ( ) ;
}
}
// Command class to set the volume of the radio
class RadioVolumeCommand implements Command
{
Radio radio;
int volumeLevel;
public RadioVolumeCommand (Radio radio, int volumeLevel)
{
this.radio = radio;
this.volumeLevel = volumeLevel;
}
public void execute ( )
{
radio.setVolume (volumeLevel) ;
}
}
Here, we will be turning on the tubelight on the button’s first click. And, on
the next click, the radio will get turned on. Next, the radio’s volume will be
set to 4 and then the tubelight will get turned off.
// Driver class
public class Driver
{
public static void main (String [ ] args)
{
RemoteControl remote = new RemoteControl ( ) ;
TubeLight tubeLight = new TubeLight ( ) ;
Radio radio = new Radio ( ) ;
// Turn on Tubelight
remote.setCommand (new
TubeLightOnCommand (tubeLight) ) ;
remote.pressButton ( ) ;
// Turn on Radio
remote.setCommand (new RadioOnCommand
(radio) ) ;
remote.pressButton ( ) ;
// Turn off Radio
remote.setCommand (new
RadioVolumeCommand (radio, 4) ) ;
remote.pressButton ( ) ;
// Turn off Tubelight
remorse.setCommand (new
TubeLightOffCommand (tubeLight) ) ;
remote.pressButton ( ) ;
}
}
TubeLight on...
Radio on ...
Radio volume set to 4
TubeLight off…
When there are too many arguments, the program will get prone to
error when passing to the Factory Class from the client in a certain
There may be optional attributes of the object. And, despite that, you
parameters as Null.
outer class: This nested class will be called the builder class.
The builder class should also have methods to set optional parameters
Finally, the build() method should be there inside the builder class to
Let’s understand better with an example. Here, we have a user class and will
build a UserBuilder class to develop objects of the user class.
class User
{
//All final attributes
private final String firstName; // required
private final String lastName; // required
private final int age; // required
private final String phoneNbr; // optional
private final String address; // optional
private final String nationality; //optional
@Override
public String toString() {
return "User: "+this.firstName+" "+this.lastName+", "+this.age+",
"+this.nationality", "+this.phoneNbr+", "+this.address;
}
System.out.println(firstUser);
System.out.println(secondUser);
User thirdUser = new User.UserBuilder("Hermoine",
"Granger").age(20).nationality("English")
//No age
//No phone
//no address
.build();
System.out.println(thirdUser);
}
}
User: Harry Potter, 30, null, 1234567, 221B Baker Street - London
User: Ron Weasley, 32, null, 5655, null
User: Hermoine Granger, 20, English, null, null
Enums are the easiest ways to create a thread-safe singleton class in Java as
the synchronization support is internally done by Java. By default, Enums are
finalized and help in averting several initializations during serialization.
They can also be created by developing the instance at the time of class
loading. This can be achieved by using static fields as the Classloader
guarantees the initialization of instances during class loading. Also, the
instance is not visible until it has been created completely.
We can use the synchronized keyword upon the getInstance method as:
In this method, you can achieve lazy initialization and the object initialization
is thread-safe because of the use of synchronized keywords.
The only issue is that the performance gets affected in the presence
of multiple threads because the entire method is synchronized.
18. Can you write a Java program to showcase the following pyramid design?
*
* *
* * *
* * * *
* * * * *
This design can be achieved through nested loops and calculatingly adding
stars and spaces as shown below:
*
* *
* * *
* * * *
* * * * *
19. Can you write a Java program to showcase the left triangle star pattern on
the system console?
*
* *
* * *
* * * *
* * * * *
20. Can you write a Java program that can print diamond number patterns?
public class MindMajixDiamondNumber{
public static void diamondNumberDisplay(int maxNum){
for (int i = 1; i <= maxNum; i++){
int n = maxNum;
for (int j = 1; j<= n - i; j++) {
System.out.print(" ");
}
for (int k = i; k >= 1; k--) {
System.out.print(k);
}
for (int l = 2; l <= i; l++) {
System.out.print(l);
}
System.out.println();
}
for (int i = maxNum-1; i >= 1; i--){
int n = maxNum-1;
for (int j = 0; j<= n - i; j++) {
System.out.print(" ");
}
for (int k = i; k >= 1; k--){
System.out.print(k);
}
for (int l = 2; l <= i; l++){
System.out.print(l);
}
System.out.println();
}
}
public static void main(String[] args) {
int n = 5;
diamondNumberDisplay(n);
}
}
1
212
32123
4321234
543212345
4321234
32123
212
1
Conclusion
Design patterns make sure that the reusable solutions are tested adequately
and implemented in a right manner to enhance the code flexibility and make
a way to develop extendible and smart solutions that solve issues with ease.
Now that you are finally preparing to appear for the interview, refer to these
design patterns interview questions and get that well-deserving job.