DesignPattern Interview Question&Answer
DesignPattern Interview Question&Answer
Questions
© Copyright by Interviewbit
Contents
Pattern Programming
29. Write a Java Program to display the pyramid as per the below design.
30. Write a Java Program to display the le triangle star pattern on the system
console.
31. Write a Java program to print Diamond Number Pattern.
32. Write a Java program that takes a String as an input and prints the pattern in the
increasing order of odd numbers as shown in the example below:
33. Write a Java program to print Pascal’s Triangle Pattern.
Design patterns are the reusable template solutions that are for solving common
problems that occur in so ware development such as repetitive code, reusable
patterns, redundant functions etc. They are similar to customizable blueprints for
solving any problem. This concept was first described by Christopher Alexander and
was later picked by 4 authors - Erich Gamma, John Vlissides, Ralph Johnson, and
Richard Helm - popularly known as the Gang of Four and published in their book
Design Patterns: Elements of Reusable Object-Oriented So ware in 1994. Design
Patterns teaches the developers how to solve commonly recurring problems without
spending too much time and effort while developing solutions to them. Due to this,
the demand for so ware developers to know these patterns has grown a lot.
In this article, we will see the most commonly asked design patterns interview
questions for both freshers and experienced professionals.
Define a pattern name and what classification of design pattern the pattern
would fall to.
Define a Problem and what is the corresponding solution
What are the variations and language-dependent alternatives for the problem
that needs to be addressed?
What are the real-time use cases and the efficiency of the so ware that uses
these patterns?
public class A{
private B b;
public A(){
this.b = new B();
}
}
Here, we have a dependency between classes A and B. If we had the IoC pattern
implemented, we would not have used the new operator to assign value to the
dependent variable. It would have been something as shown below:
public class A {
private IocB b;
public A(IocB b) {
this.b = b;
}
}
We have inverted the control of handing the dependency of instantiating the object
of class B to the IoC class IocB .
The Open close principle states that any class, component or entity should be open
for extension but closed for modification. A class can be extended via Inheritance,
Interfaces, Composition whenever required instead of modifying the code of the
class. Consider an instance where we have a class that calculates the area of a square.
Later, we get the requirement of calculating the area of a rectangle. Here, instead of
modifying the original class, we can create one base class and this base class can be
extended by the new class rectangle.
Both Design Patterns and Algorithms describe typical solutions to any given problem.
But the main difference is that the algorithm defines a clear set of actions for
achieving a goal and a design pattern provides a high-level description of any
solution. Design patterns applied to two different problems might be the same but
the logic of implementation would be different and is based on the requirements.
Now to implement the factory design pattern for the above example, let us follow the
below steps:
Step 1: Create a Shape interface.
//Shape.java
public interface Shape {
void draw();
}
Step 2: Create concrete classes Rectangle, Square, Triangle that implements the
Shape interface.
//Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Rectangle Drawn");
}
}
//Square.java
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Square Drawn");
}
}
//Triangle.java
public class Triangle implements Shape {
@Override
public void draw() {
System.out.println("Triangle Drawn");
}
}
//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: Implement the Driver class and utilise the factory class for getting the
object of the required type.
//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
Let us understand this with the help of an example of a USB to Ethernet adapter that
is used when we have an ethernet interface at one end and the USB interface on the
other end. The USB and ethernet are incompatible with each other which is why we
require an adapter. The adapter class has a Client class that expects some object type
and it has an Adaptee class that offers the same feature but by exposing a different
interface. Now to make these both communicate, we have an Adapter class. The
client requests the Adapter by using the target interface. The Adapter class translates
the request using the Adaptee Interface on the adaptee. The Client receives the
results unaware of the adapter’s role. This has been described in the class diagram as
shown below:
Class Diagram:
//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.println("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 file) {
System.out.println("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");
}
}
The above image is the UML representation of the Bridge Pattern. There are 4 main
elements of Bridge Pattern. They are:
Abstraction – This is the core of the pattern and it defines its crux. This contains
a reference to the implementer.
Refined Abstraction – This extends the abstraction and takes refined details of
the requirements and hides it from the implementors.
Implementer – This is the interface for the implementation classes.
Concrete Implementation – These are the concrete implementation classes
that implement the Implementer interface.
Java lets to extend only one class and let’s implement multiple interfaces. If we
extend one class then we cannot extend other classes. In such cases, it is better
to implement the interfaces wherever possible and reserve the inheritance of
classes to only important ones.
Interfaces are used for representing the behaviour of the class. Java lets to
implement multiple interfaces which is why we can take the help of interfaces to
help classes have multiple behaviours at the same time.
Abstract classes are slightly faster than interfaces. It can be used for time-critical
applications.
In cases where there are common behaviours across the inheritance hierarchy,
these can be coded at one place in abstract classes. Interfaces and abstract
classes can also be used together to define a function in interface and
functionality in abstract class.
The above image represents the UML diagram of this pattern. There are 3
components of this design, they are:
Client: This is the point of request origination and the component that accesses
the handler for handling the request.
Handler: Handler can either be a class or an interface that received the request
primarily and dispatches it to the chain of handlers. This Handler knows only the
first handler of the chain.
Concrete Handlers: These are the actual request handlers in sequential order.
This pattern can be used in the following cases:
Whenever we want to decouple the sender and the receiver of the request.
Whenever we want multiple objects to handle a request at runtime.
Whenever we do not want to explicitly specify handlers in the code.
Whenever we want to issue a request to several objects without explicitly
specifying handlers.
Decorator design pattern belongs to the category of structural pattern that lets users
add new features to an existing object without modifying the structure. This pattern
creates a class called decorator class that acts as a wrapper to the existing class by
keeping the signatures of class methods intact. This pattern makes use of abstract
classes and interfaces with composition for implementing the wrapper. They are
mostly used to apply SRP (Single Responsibility Principle) as we divide functionalities
into classes with unique concerns. This pattern is structurally similar to the chain of
responsibility pattern. Following are the steps to implement decorator design
pattern:
Create an interface and concrete classes that implement this interface.
Create an abstract decorator class that implements the above interface.
Create a concrete decorator class that extends the above abstract class.
Use the concrete decorator class to decorate the interface objects and verify the
output.
Let us understand this with the help of an example. Here, we will be creating a Shape
Interface and concrete classes- Rectangle and Triangle that implement this Shape
interface. We will be creating an abstract decorator class “ShapeDecorator” that
implements the Shape interface. We will create RedColorDecorator that extends
ShapeDecorator. We will be then using this decorator to implement the
functionalities.
// Shape.java
public interface Shape {
void draw();
}
// Rectangle.java
public class Rectangle implements Shape {
// Overriding the draw method
@Override public void draw()
{
System.out.println("Rectangle Drawn...");
}
}
// Triangle.java
public class Triangle implements Shape {
// Overriding the draw method
@Override public void draw()
{
System.out.println("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[] args)
{
Validate the output. The output of the above code would be:
Triangle Drawn...
.........
Triangle Drawn...
Red color border added...
.........
Rectangle Drawn...
Red color border added...
.........
We have a client that calls the invoker to run a command. We have a Command
interface that acts as an abstraction to the underlying concrete classes. Let us
understand this with the help of an example of remote control that has only one
button. Using this button, we will be controlling the behaviour of two objects
tubelight and a radio. The command to control the objects will be implemented
using the command design pattern.
Create Command interface:
// Command Interface
interface Command
{
public void execute();
}
Create Tubelight class and its command classes that extend the above interface
to control the tubelight.
// Tubelight class
class TubeLight
{
public void lightOn(){
System.out.println("TubeLight on...");
}
public void lightOff(){
System.out.println("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();
}
}
Create a Radio class and its command classes that extend the above interface to
control the radio.
// Radio class
class Radio
{
public void radioOn()
{
System.out.println("Radio on ...");
}
public void radioOff()
{
System.out.println("Radio off...");
}
public void setVolume(int volumeLevel)
{
// code to set the volume
System.out.println("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);
}
}
Create a remote control class that has only one button and on click of the
button, execute the command functionality:
Create a Driver class to implement the pattern. Here we will be first turning on
the tubelight on the first click of the button, on next click, we will be turning on
the radio, then we will be setting the volume of the radio to 4 and then we will
be turning off the tubelight.
// 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
remote.setCommand(new TubeLightOffCommand(tubeLight));
remote.pressButton();
}
}
Validate the result of this pattern to see if it’s working fine. The result of this
code would be:
TubeLight on...
Radio on ...
Radio volume set to 4
TubeLight off...
A builder pattern is a type of creational design pattern that lets to construct complex
objects in a step by step manner. The pattern lets to produce different
representations of an object using the same construction logic. It helps in creating
immutable classes having a large set of attributes. In the Factory and Abstract Factory
Design Patterns, we encounter the following issues if the object contains a lot of
attributes:
When the arguments are too many, the program will be error-prone while
passing from the client to the Factory Class in a specific order. It becomes
tedious to maintain the order of arguments when the types are the same.
There might be some optional attributes of the object and yet we would be
forced to send all parameters and optional attributes as Null.
When the object creation becomes complex due to heavy attributes, the
complexity of this class would become confusing.
The above problems can also be solved by using constructors of required parameters
alone. But this causes an issue when there would be new parameters that are added
as part of new requirements. This would result in inconsistency. That’s where Builder
comes into the picture. This pattern solves the issue of a large number of optional
attributes and the inconsistent state by providing means to build an object in a step-
by-step way and return the final object utilizing another method.
Builder pattern can be implemented by following the below steps:
Create a static nested class, copy all arguments from the outer class. This nested
class would be called the Builder class.
Proper naming convention has to be followed while naming this builder
class. For example, if the name of the class is Interviewbit , then the
name of the builder would be InterviewbitBuilder .
The builder class should have a public constructor with all required attributes
sent as parameters.
The builder class should have methods for setting optional parameters and
return the same builder object post setting these values.
The last step is to have a build() method inside the builder class that returns the
Object needed by the client. This would require a private constructor in the class
that takes the Builder class as the parameter.
Following is the sample example of the builder pattern implementation. We have a
User class and we will be building UserBuilder class to build the 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.nationa
}
User: Harry Potter, 30, null, 1234567, 221B Baker Street - London
User: Ron Weasley, 32, null, 5655, null
User: Hermoine Granger, 20, English, null, null
The above image represents how the request flow happens in the MVC Pattern. First,
the Browser (client) sends request for a page to the controller of the server. The
controller invokes the model, retrieves the data and sends the response. The
response is then sent to the view for rendering. The view will be rendered and it is
sent back to the client for display.
Prototype design pattern is used for creating duplicate objects based on the
prototype of the already existing object using cloning. Doing this has a positive
impact on the performance of object creation. Creating objects using the new
keyword requires a lot of resources and is a heavyweight process that impacts
performance. Hence, the prototype design pattern is more advantageous than the
object created using a new keyword.
But the disadvantage of this way is that the initialization cannot be done lazily and
the getInstance() method is called even before any client can call.
Using synchronized keyword: We can make use of the synchronized keyword
upon the getInstance method as shown below.
In this method, we can achieve lazy initialization, and also since we use
synchronized keywords, the object initialization is thread-safe.
The only problem is that since the whole method is synchronized, the
performance is impacted in the presence of multiple threads.
Pattern Programming
*
* *
* * *
* * * *
* * * * *
This can be achieved by using nested loops and calculatingly adding spaces and stars
as shown in the logic below:
Output:
*
* *
* * *
* * * *
* * * * *
Output:
*
* *
* * *
* * * *
* * * * *
}
}
Output:
1
212
32123
4321234
543212345
4321234
32123
212
1
Solution:
import java.util.Scanner;
public class InterviewBitStringPattern{
public static void printStringPattern(String input){
for (int i = 1; i <= input.length(); i++) {
for (int j = input.length(); j > i; j--){
System.out.print(" ");
}
for (int k = i * 2 - 1; k >= 1; k--){
System.out.print(input.charAt(i - 1));
}
System.out.println("");
}
}
public static void main(String[] args) {
// to create a new Scanner object
Scanner scanner = new Scanner(System.in);
// to get the String from the user
System.out.println("Enter Input String: ");
String input = scanner.nextLine();
System.out.println("Printing Pattern.....");
printStringPattern(input);
}
}
Output:
Output:
1
1 1
1 2 1
1 3
1 3
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
Conclusion
Design Patterns ensure that the reusable solutions that are well-tested are
implemented which improves the code flexibility and paves way for developing smart
and extendible solutions that solve problems easily. Due to this, the demand for
so ware developers to know the best design practices and implementation has been
rising steadily. These are generally discussed in the LLD (Low-Level Design) round of
the company interviews. In this article, we have covered the most commonly asked
design patterns interview questions for both freshers and experienced so ware
professionals.
Useful Resources:
Java Interview Questions
System Design
Practice
Css Interview Questions Laravel Interview Questions Asp Net Interview Questions