Design patterns are best practices for designing architecture and maintaining code more efficiently. They provide reusable solutions to common problems for object-oriented programming in the software development world.
1.Creational Design Pattern:
This pattern guides us in the creation of objects and details how objects are instantiated and managed.
Factory Design Pattern:
In this pattern when client want to get an object using the interface and keep the abstraction to object creation logic so that client won't know the object creation logic.
package DesignPatterns;
public class FactoryDesignPattern {
private CardFactory cardFactory;
public void setCardFactory(CardFactory cardFactory) {
this.cardFactory = cardFactory;
}
public void createCard() {
Card card = cardFactory.createCard();
int amount = card.getAmount();
System.out.println("Amount: " + amount);
}
public static void main(String[] args) {
FactoryDesignPattern factoryDesignPattern = new FactoryDesignPattern();
factoryDesignPattern.setCardFactory(new CreditCardFactory());
factoryDesignPattern.createCard();
factoryDesignPattern.setCardFactory(new DebitCardFactory());
factoryDesignPattern.createCard();
// Setting VisaCardFactory as the card factory
factoryDesignPattern.setCardFactory(new VisaCardFactory());
factoryDesignPattern.createCard(); // Creates a VisaCard
}
}
interface Card {
int getAmount();
}
interface CardFactory {
Card createCard();
}
class Debit implements Card {
@Override
public int getAmount() {
return 1;
}
}
class Credit implements Card {
@Override
public int getAmount() {
return 10;
}
}
class Visa implements Card {
@Override
public int getAmount() {
return 5;
}
}
class CreditCardFactory implements CardFactory {
@Override
public Card createCard() {
return new Credit();
}
}
class DebitCardFactory implements CardFactory {
@Override
public Card createCard() {
return new Debit();
}
}
class VisaCardFactory implements CardFactory {
@Override
public Card createCard() {
return new Visa();
}
}
Abstract Factory Design Pattern:
It is similar to factory design pattern but here one more layer will add. it is a factory of factories which is related to similar type of objects.
package DesignPatterns;
public class AbstractFactoryDesignPattern {
private AbstractCardFactory abstractCardFactory;
public void setAbstractCardFactory(AbstractCardFactory abstractCardFactory) {
this.abstractCardFactory = abstractCardFactory;
}
public void createCards() {
Card creditCard = abstractCardFactory.createCreditCard();
Card debitCard = abstractCardFactory.createDebitCard();
int creditAmount = creditCard.getAmount();
int debitAmount = debitCard.getAmount();
System.out.println("Credit Card Amount: " + creditAmount);
System.out.println("Debit Card Amount: " + debitAmount);
}
public static void main(String[] args) {
AbstractFactoryDesignPattern client = new AbstractFactoryDesignPattern();
client.setAbstractCardFactory(new ConcreteCardFactory());
client.createCards();
}
}
interface Card {
int getAmount();
}
interface AbstractCardFactory {
Card createCreditCard();
Card createDebitCard();
}
class Debit implements Card {
@Override
public int getAmount() {
return 1;
}
}
class Credit implements Card {
@Override
public int getAmount() {
return 10;
}
}
class ConcreteCardFactory implements AbstractCardFactory {
@Override
public Card createCreditCard() {
return new Credit();
}
@Override
public Card createDebitCard() {
return new Debit();
}
}
.
Singleton Design Pattern:
This pattern which is responsible to create only one object for a single class and we won't be able to create another object for same class. keeping private modifier to the constructor and create a static method to get Instance.
This class provides a way to access an object without instantiate the object of a class.
package DesignPatterns;
public class SingleDesignPattern {
private static SingleDesignPattern pattern;
private SingleDesignPattern(){
}
public static SingleDesignPattern getInstance(){
if(pattern==null){
pattern=new SingleDesignPattern();
}
return pattern;
}
}
Prototype Design Pattern:
This pattern creates a duplicate object for a current object by using cloning mechanisms. It allows for the creation of new instances by copying an existing instance, serving as a prototype.
it created caching to reduce our database calls.
package DesignPatterns;
public class PrototypeDesignPattern {
public static void main(String[] args) {
Shape shape=new Shape();
try {
Shape clone = (Shape)shape.clone();
System.out.println(clone.hashCode());
System.out.println(clone.getName());
Shape c=(Shape)shape.clone();
System.out.println(c.getName());
System.out.println(c.hashCode());
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
}
}
class Shape implements Cloneable {
public String name;
public String getName(){
return "nithin";
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Builder Design Pattern:
The Builder Design Pattern is a creational design pattern that is used to construct a complex object step by step.
Example-StringBuffer.
2.Structural Design Patterns:
Structural design patterns provide guidelines on how to organize and connect classes and objects to from a larger structure's, making your code more flexible and maintainable.
Adapter Design Pattern:
In context of Adpater Design Pattern, if two incompatible types need to communicate, you can introduce an adapter that sits between them and allows them to work together seamlessly. The Adapter Pattern is a structural pattern that enables the interaction between interfaces that are incompatible or would not work well together otherwise.
Example: Adapter Design Pattern in Real Life
Imagine you receive a laptop from a friend in the U.S., and as you attempt to charge it in India, you encounter a challenge – the charger's U.S. plug doesn't fit into the Indian power outlet. To resolve this incompatibility and ensure seamless charging, you wisely opt for an adapter. by adapter we can connect the two different incompatible types.
interface USCharger {
void charge();
}
interface IndianPlug {
void plug();
}
class USChargerImpl implements USCharger {
public void charge() {
System.out.print("US charger");
}
}
class Adapter implements IndianPlug {
private USCharger usCharger;
public Adapter(USCharger usCharger) {
this.usCharger = usCharger;
}
public void plug() {
usCharger.charge();
}
}
public class PlugCharger {
public static void main(String[] args) {
USCharger usCharger = new USChargerImpl();
Adapter adapter = new Adapter(usCharger);
adapter.plug();
}
}
Facade Design Pattern:
Facade pattern is a structural design pattern that provides a simplified interface to a set of interfaces in the subsystem. Which reduces client interaction, and it hides the complexity of a subsystem from client.
Imagine a scenario where posting a picture on social media is as easy as a single click. This seamless process is made possible through the use of the Facade design pattern. The beauty of this pattern lies in its ability to shield users from the intricacies of the internal workings, providing a clean and simple interface for a complex operation. internal it calls many functions like set path, store in database, upload in social media.
class ImagePath {
public void setPath() {
System.out.println("Setting path for image");
}
}
class StoreImage {
public void store() {
System.out.println("Storing image");
}
}
class UploadSocialMedia {
public void upload() {
System.out.println("Uploading to social media");
}
}
interface PostImage {
void uploadImage();
}
class DefaultPostImage implements PostImage {
private ImagePath imagePath;
private StoreImage storeImage;
private UploadSocialMedia uploadSocialMedia;
public DefaultPostImage() {
this.imagePath = new ImagePath();
this.storeImage = new StoreImage();
this.uploadSocialMedia = new UploadSocialMedia();
}
public void uploadImage() {
imagePath.setPath();
storeImage.store();
uploadSocialMedia.upload();
}
}
class Main {
public static void main(String[] args) {
PostImage p = new DefaultPostImage();
p.uploadImage();
}
}
Fly-Weight Design Pattern:
Flyweight is a structural design pattern which helps to reduces the RAM usages, it simplifies the object creation, it referenced to a shared object (which have intrinsic properties) .
Decorator Design Pattern
This is a structural design pattern it defines the adding new features to an object dynamically without changing the structure of the code.
3.Behavioral Design Pattern
It defines effective ways for objects to interact, communicate, and collaborate while maintaining loose coupling.
Strategy Design Pattern:
A Strategy Pattern says that "defines a family of functionality, encapsulate each one, and make them interchangeable".
it follows three strategies:
1.Favor composition over inheritance.
2. Always code with interfaces.
Observer Design Pattern:
The Observer Design Pattern follows the publisher-subscriber model, also known as the pub-sub model.
Example when we subscribe a channel. Then in that channel any new post is uploaded we get a notification. This follows Observer design pattern.