Java Design Patterns 2021
Design patterns are best practices to general problems that software developers faced during software development. Design patterns are primarily based on object orientated design principles of,
- Program to an interface not an implementation
- Favor object composition over inheritance
Types of Design Patterns
- Creational —hides the object creation logic
- Structural — focus on class and object composition
- Behavioral — focus on communication between objects.
- J2EE — focus on presentation tier
Factory Pattern
Create the object without exposing the creation logic and access the object using a common interface.
ShapeFactory shapeFactory = new ShapeFactory();
Shape shape1 = shapeFactory.getShape("CIRCLE");
Shape shape2 = shapeFactory.getShape("RECTANGLE");In this example shapefactory creates the required shape based on the parameter passed in. Inside the shapefactory it has the normal shape creation logic. Shape is an interface used by other objects.
Abstract Factory Pattern
Patterns creates other factories acts like factory of factories.
AbstractFactory shapeFactory = FactoryProducer.getFactory("rounded");
Shape shape1 = shapeFactory.getShape("RECTANGLE");
Shape shape2 = shapeFactory.getShape("SQUARE"); //get boxed shape factory
AbstractFactory shapeFactory1 = FactoryProducer.getFactory("boxed");
Shape shape3 = shapeFactory1.getShape("RECTANGLE");
Shape shape4 = shapeFactory1.getShape("SQUARE");
shape 1 & 2 has rounded corners and 3 & 4 has boxed corners.
Singleton Pattern
This patterns allows creating only a single object. This is achieved by limiting access to object via class only.
public class SingleObject {
private static SingleObject instance = new SingleObject();
//make the constructor private - not to instantiated
private SingleObject(){}
//make static - can access class method directly
public static SingleObject getInstance(){
return instance;
}
}This object can be accessed via getInstance() only.
Builder Pattern
We will use builder pattern instead of factory pattern when the object creation is complex.
MealBuilder mealBuilder= new MealBuilder();
Meal vegMeal = mealBuilder.addVegBurger()
.addCoke()
.build()when we execute build() it may use few other objects to create the meal object as bellow.
private vegBurger, coke;
MealBuilder addVegBurger(){
vegBurger=new vegBurger()
return this;
}
MealBuilder addCoke(){
coke=new coke()
return this;
}
Meal build(){
Meal meal=new Meal();
meal.setVegBurger(this.vegBurger);
meal.setCoke(this.coke);}
Prototype Pattern
Is the creation of object using existing objects when object creation is time consuming, and costly.
Shape clonedShape = (Shape) ShapeCache.getShape("1");
Shape clonedShape2 = (Shape) ShapeCache.getShape("2");getShape will be returning a cloned object
public static Shape getShape(String shapeId) {
Shape cachedShape = shapeMap.get(shapeId);
return (Shape) cachedShape.clone();
}shapeMap is created like this
Circle circle = new Circle();
circle.setId("1");
shapeMap.put(circle.getId(),circle);
...
shapeMap.put(square.getId(),square);
shapeMap.put(rectangle.getId(), rectangle);Ref: https://www.tutorialspoint.com/design_pattern/prototype_pattern.htm
Adapter Pattern
works as a bridge between two incompatible interfaces. It’s like a card reader acts as an adapter between memory card and a laptop.
class Sparrow {
public void makeSound() { println("Chirp Chirp"); }
}class ToyDuck {
public void squeak() { println("Squeak")}
}
what if sparrow wants to squeak?
Sparrow sparrow = new Sparrow();
ToyDuck sparrowAsDuck = new BirdAdapter(sparrow);
sparrowAsDuck.squeak();BirdAdapter class may have a method like this
public void squeak() {
Sparrow.makeSound();
}Basically methods are matched at adapter class. https://www.geeksforgeeks.org/adapter-pattern/
Bridge Pattern*
This pattern involves an interface which acts as a bridge which makes the functionality of concrete classes independent from interface implementer classes. Both types of classes can be altered structurally without affecting each other.
The display of different image formats on different operating systems is a good example of the Bridge pattern. The image structure is the same across all operating systems, but the how it’s viewed (the implementation) is different on each OS.
public interface TV{
public void on();}public class Sony implements TV{
public void on(){//Sony specific on}}public class Philips implements TV{
public void on(){//Philips specific on}}public abstract class RemoteControl{
private TV implementor;
public void on() { implementor.on(); }
}
Now we have a pretty standard remote control. And what if we need a picture in picture feature in the remote control.
public class ConcreteRemote extends RemoteControl{
public void pip() {
//pip implementation
}
}In this example tv features will involve separately and remote control separately too as both has too separate interfaces.
Ref: https://dzone.com/articles/design-patterns-bridge
Filter/Criteria Pattern
enables to filter a set of objects using different criteria and chaining them in a decoupled way through logical operations.
persons.add(new Person("Robert","Male", "Single"));
persons.add(new Person("John", "Male", "Married"));
Criteria singleMale = new AndCriteria(single, male);
singleMale.meetCriteria(persons)https://www.tutorialspoint.com/design_pattern/filter_pattern.htm
Composite Pattern
is used where we need to treat a group of objects like a single object.
Employee CEO = new Employee("John","CEO", 30000);Employee headSales = new Employee("Robert","Head Sales", 20000);CEO.add(headSales);
May be we can print all child objects by looping through all the childrens of ceo object
for (Employee headEmployee : CEO.getSubordinates()) {
System.out.println(headEmployee);Decorator Pattern
Allow adding new functionality to an existing object without altering its structure.
Shape circle = new Circle();Shape redCircle = new RedShapeDecorator(new Circle());
Facade Pattern
hides the complexities of the system and provides an interface to access.
ShapeMaker shapeMaker = new ShapeMaker();
shapeMaker.drawCircle();
shapeMaker.drawRectangle();ShapeMaker is the facade class has following implementation
Shape circle = new Circle();
Shape rectangle = new Rectangle();public void drawCircle(){
circle.draw();
}
public void drawRectangle(){
rectangle.draw();
}
Flyweight Pattern
Flyweight pattern tries to reuse already existing objects by storing them. to reduce the number of objects created and to decrease memory footprint and increase performance.
public class ShapeFactory {
private static final HashMap circleMap = new HashMap();
public static Shape getCircle(String color) {
Circle circle = (Circle)circleMap.get(color);
if(circle == null) {
circle = new Circle(color);
circleMap.put(color, circle);
}
return circle;
}
}Whenever a request comes it checks the circle object in its HashMap before creating a new one.
Proxy Pattern
a class represents functionality of another class to outer world.
class ProxyImage {
private RealImage realImage;
public void display() {
if(realImage == null){
realImage = new RealImage();
}
realImage.display();
}
}Creates the real image only if its not creates before
Chain of Responsibility Pattern
each receiver contains reference to another receiver. creates a chain of receiver objects for a request. decouples sender and receiver of a request based on type of request.
AbstractLogger loggerChain = getChainOfLoggers();
loggerChain.logMessage(AbstractLogger.INFO,"info.");getChainOfLoggers() will create objects will link them via setNextLogger()
private static AbstractLogger getChainOfLoggers(){
AbstractLogger error = new ErrorLogger(AbstractLogger.ERROR);
AbstractLogger file = new FileLogger(AbstractLogger.DEBUG);
error.setNextLogger(file);
return error;
}When logMessage() is called will write the message and if next logger is available it also will be invoked.
public void logMessage(int level, String message){
if(this.level <= level){
write(message);
}
if(nextLogger !=null){
nextLogger.logMessage(level, message);
}
}https://www.tutorialspoint.com/design_pattern/chain_of_responsibility_pattern.htm
Command Pattern
A request is wrapped under an object as command and passed to invoker object. Invoker object looks for the appropriate object which can handle this command.
Stock abcStock = new Stock();
BuyStock buyStockOrder = new BuyStock(abcStock);
SellStock sellStockOrder = new SellStock(abcStock);
Broker broker = new Broker();
broker.takeOrder(buyStockOrder);
broker.takeOrder(sellStockOrder);
broker.placeOrders();placeOrder() of the Broker class invokes execute()
public void placeOrders(){
for (Order order : orderList) {
order.execute();
}
}execute() will be buy or sell based on the class
public class SellStock implements Order {
private Stock abcStock;
public void execute() {
abcStock.sell();
}
}public class BuyStock implements Order {
private Stock abcStock;
public void execute() {
abcStock.buy();
}
}
https://www.tutorialspoint.com/design_pattern/command_pattern.htm
Interpreter Pattern
provides a way to evaluate language grammar or expression. This involves implementing an expression interface which tells to interpret a particular context. This is used in SQL parsing, symbol processing engine etc.
//Rule: Julie is a married women
public static Expression getMarriedWomanExpression(){
Expression julie = new TerminalExpression("Julie");
Expression married = new TerminalExpression("Married");
return new AndExpression(julie, married);
}Check the rule
Expression isMarriedWoman = getMarriedWomanExpression();
System.out.println("Julie is a married women? " + isMarriedWoman.interpret("Married Julie"));AndExpression.interpret() will return true if text in the rule objects is in the message we verify
Ref: https://www.tutorialspoint.com/design_pattern/interpreter_pattern.htm
Iterator Pattern
Can access the elements of a collection object in sequential manner without knowing its underlying representation.
for(Iterator iter = sample.getIterator(); iter.hasNext();){
String name = (String)iter.next();
System.out.println("Name : " + name);
}hasNext() and next() can be implemented like this
public String names[] = {"Robert" , "John" ,"Julie" , "Lora"};public boolean hasNext() {
if(index < names.length){
return true;
}
return false;
}
public Object next() {
if(this.hasNext()){
return names[index++];
}
return null;
}
https://www.tutorialspoint.com/design_pattern/iterator_pattern.htm
Mediator Pattern
Reduces communication complexity between multiple objects or classes. A mediator class will handle all the communications. supports easy maintenance of the code by loose coupling. Ex: chat room
User john = new User("John");
robert.sendMessage("Hi! John!");users send message to chat room where user object will act as mediator object.
public void sendMessage(String message){
ChatRoom.showMessage(this,message);
}chat room to show the messages to all users
public static void showMessage(User user, String message){
System.out.println( message);
}Memento Pattern
to restore state of an object to a previous state.
It has three actor classes Memento contains state of an object to be restored. Originator creates and stores states in Memento objects and Caretaker object is responsible to restore object state from Memento.
originator.setState("State #1");
careTaker.add(originator.saveStateToMemento());
originator.getStateFromMemento(careTaker.get(0));Observer Pattern
To communicate to dependents when there is one-to-many relationship between objects. 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.
Subject subject = new Subject();
new HexaObserver(subject);subject class is created and observer class is extended to HexaObserver.
public class HexaObserver extends Observer{
protected Subject subject;
public HexaObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}}now subject is attached to HexaObserver object internally.
Get Nuwan Zen’s stories in your inbox
Join Medium for free to get updates from this writer.
https://www.tutorialspoint.com/design_pattern/observer_pattern.htm
State Pattern
class behavior changes based on its state.
Context context = new Context();
StartState startState = new StartState();
startState.doAction(context);
StopState stopState = new StopState();
stopState.doAction(context);
we can change the state of the context based on the object its been passed. This method resides in StartState and StopState classes.
public void doAction(Context context) {
context.setState(this);
}https://www.tutorialspoint.com/design_pattern/state_pattern.htm
Null Object Pattern
a null object replaces check of NULL object instance. provide default behaviour in case data is not available.
public static AbstractCustomer getCustomer(String name){
if (names.equalsIgnoreCase(name)){
return new RealCustomer(name);
}
return new NullCustomer();
}null customer could be
public class NullCustomer{
public String getName() {
return "Not Available in Customer Database";
}
public boolean isNil() {
return true;
}
}https://www.tutorialspoint.com/design_pattern/null_object_pattern.htm
Strategy Pattern
a class behavior can be changed at run time.
Context context = new Context(new OperationAdd());
context.executeStrategy(10, 5);
context = new Context(new OperationMultiply());
context.executeStrategy(10, 5);Context class
public Context(Strategy strategy){
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2){
return strategy.doOperation(num1, num2);
}behavior is copied from the passed in parameter, implementation of doOperation will be coming from OperationAdd or OperationMultiply classes.
https://www.tutorialspoint.com/design_pattern/strategy_pattern.htm
Template Pattern
an abstract class exposes defines templates for subclass methods.
public abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
//template method
public final void play(){
//initialize the game
initialize();
//start game
startPlay();
//end game
endPlay();
}
}when cricket class is inhertited from game class it will follow the template provided. note the final contructor in Game class.
Game game = new Cricket();
game.play();https://www.tutorialspoint.com/design_pattern/template_pattern.htm
Visitor Pattern*
In Visitor pattern, we use a visitor class which changes the executing algorithm of an element class. By this way, execution algorithm of element can vary as and when visitor varies. element object has to accept the visitor object so that visitor object handles the operation on the element object.
computer.accept(new Visitor());Computer
public void accept(Visitor visitor) {
mouse.accept(visitor);
visitor.visit(this);
}Visitor
public void visit(Mouse mouse) {
System.out.println("Displaying Mouse.");
}
public void visit(Computer computer) {
System.out.println("Displaying Computer.");
}Mouse
public void accept(Visitor visitor) {
visitor.visit(this);
}https://www.tutorialspoint.com/design_pattern/visitor_pattern.htm
MVC Pattern
separate application’s concerns to
- Model — object or JAVA POJO carrying data. It can also have logic to update controller if its data changes.
- View — visualization of the data that model contains.
- Controller — Controller acts on both model and view. It controls the data flow into model object and updates the view whenever data changes. It keeps view and model separate.
Student model = new Student();
StudentView view = new StudentView();
StudentController controller = new StudentController(model, view);
controller.updateView();StudentController
public void updateView(){
view.printStudentDetails(model.getName(), model.getRollNo());
}updateview method will call the view object to print the data.
https://www.tutorialspoint.com/design_pattern/mvc_pattern.htm
Business Delegate Pattern
Decouples presentation tier and business tier.
- Client — Presentation tier code may be JSP, servlet or UI java code.
- Business Delegate — entry point to access Business Service methods.
- LookUp Service —get relative business implementation and provide business object access to business delegate object.
- Business Service — provide actual business implementation logic.
BusinessDelegate businessDelegate = new BusinessDelegate();
Client client = new Client(businessDelegate);businessDelegate.setServiceType("EJB");
client.doTask();
businessDelegate.setServiceType("JMS");
client.doTask();
doTask method, this will call the print method of the returned object.
businessService = lookupService.getBusinessService(serviceType);
businessService.print();getBusinessService will return object based on input type
if(serviceType.equalsIgnoreCase("EJB")){
return new EJBService();
}
else {
return new JMSService();
}client > delegate > lookup > service
https://www.tutorialspoint.com/design_pattern/business_delegate_pattern.htm
Composite Entity Pattern*
Composite Entity pattern is used in EJB persistence mechanism. A Composite entity is an EJB entity bean which represents a graph of objects. When a composite entity is updated, internally dependent objects beans get updated automatically as being managed by EJB entity bean.
Client client = new Client();
client.setData("Test", "Data");
client.printData();class Client
public void printData(){
print( compositeEntity.getData());
}
public void setData(String data1, String data2){
compositeEntity.setData(data1, data2);
}class CompositeEntity
public void setData(String data1, String data2){
CoarseGrainedObject.setData(data1, data2);
}
public String[] getData(){
return CoarseGrainedObject.getData();
}https://www.tutorialspoint.com/design_pattern/composite_entity_pattern.htm
Data Access Object Pattern
DAO pattern is used to separate low level data accessing API or operations from high level business services. participants
- Data Access Object Interface — defines the standard operations to be performed on a model object(s).
- Data Access Object concrete class — implements above interface. responsible to get data from a data source
- Model Object or Value Object — simple POJO containing get/set methods to store data retrieved using DAO class.
StudentDao studentDao = new StudentDaoImpl();
Student student =studentDao.getAllStudents().get(0);
student.setName("Michael");
studentDao.updateStudent(student);class StudentDaoImpl
public List<Student> getAllStudents() {
return students;
}public void updateStudent(Student student) {
students.get(student.getRollNo()).setName(student.getName());
}
class Student
public void setName(String name) {
this.name = name;
}https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm
Front Controller Pattern
provide a centralized request handling mechanism so that all requests will be handled by a single handler. This handler can do the authentication/ authorization/ logging or tracking of request and then pass the requests to corresponding handlers. entities,
- Front Controller — Single handler for all kinds of requests coming to the application (either web based/ desktop based).
- Dispatcher — dispatch the request to corresponding specific handler.
- View — Views are the object for which the requests are made.
FrontController frontController = new FrontController();
frontController.dispatchRequest("HOME");
frontController.dispatchRequest("STUDENT");class FrontController
dispatcher = new Dispatcher();public void dispatchRequest(String request){
if(isAuthenticUser()){
dispatcher.dispatch(request);
}
}
class Dispatcher
studentView = new StudentView();
homeView = new HomeView();public void dispatch(String request){
if(request.equalsIgnoreCase("STUDENT")){
studentView.show();
}
else{
homeView.show();
}
}
https://www.tutorialspoint.com/design_pattern/front_controller_pattern.htm
Intercepting Filter Pattern
to do some pre-processing / post-processing. Filters can do the authentication/ authorization/ logging or tracking of request and then pass the requests to corresponding handlers.
- Filter — performs task prior or after execution of request handler.
- Filter Chain —carries multiple filters and execute in order.
- Target — request handler
- Filter Manager — manages the filters and Filter Chain.
- Client — sends request to the Target object.
FilterManager filterManager = new FilterManager(new Target());
filterManager.setFilter(new AuthenticationFilter());
filterManager.setFilter(new DebugFilter());
Client client = new Client();
client.setFilterManager(filterManager);
client.sendRequest("HOME");class Client
public void sendRequest(String request){
filterManager.filterRequest(request);
}class FilterManager
filterChain.setTarget(target);
public void filterRequest(String request){
filterChain.execute(request);
}class FilterChain
public void execute(String request){
for (Filter filter : filters) {
filter.execute(request);
}
target.execute(request);
}https://www.tutorialspoint.com/design_pattern/intercepting_filter_pattern.htm
Service Locator Pattern
To locate services using JNDI lookup. Caches the service object for performance.
- Service — Actual Service which will process the request. Reference of such service is to be looked upon in JNDI server.
- Context / Initial Context — JNDI Context carries the reference to service used for lookup purpose.
- Service Locator — Service Locator is a single point of contact to get services by JNDI lookup caching the services.
- Cache — Cache to store references of services to reuse them
- Client — Client is the object that invokes the services via ServiceLocator.
Service service = ServiceLocator.getService("Service1");
service.execute();class ServiceLocator
private static Cache cache;
static {
cache = new Cache();
}
public static Service getService(String jndiName){
Service service = cache.getService(jndiName);
if(service != null){
return service;
}
InitialContext context = new InitialContext();
Service service1 = (Service)context.lookup(jndiName);
cache.addService(service1);
return service1;
}InitialContext will return service object based on jndi name, cache will store that object in a list.
https://www.tutorialspoint.com/design_pattern/service_locator_pattern.htm
Transfer Object Pattern
To pass data with multiple attributes in one shot from client to server. Transfer Object is a simple POJO class having getter/setter methods and is serializable so that it can be transferred over the network.
StudentBO s = new StudentBO(); //update student
StudentVO student = s.getAllStudents().get(0);
student.setName("Michael");
s.updateStudent(student);
class StudentBO is the Business Object.
List<StudentVO> students;public void updateStudent(StudentVO student) {
students.get(student.getRollNo()).setName(student.getName());
}public List<StudentVO> getAllStudents() {
return students;
}
StudentVO is the Transfer Object. its a pojo class.
https://www.tutorialspoint.com/design_pattern/transfer_object_pattern.htm
Read my other blogs:







