[Go to site: main page, start]

0% found this document useful (0 votes)
33 views9 pages

Practical Java Design Patterns Guide

The document describes five design patterns in software development: Singleton, Factory, Abstract Factory, Builder, and Prototype. Each pattern is illustrated with Java code examples that demonstrate their implementation and usage. These patterns help in creating efficient and maintainable code by managing object creation and relationships effectively.

Uploaded by

suresh
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views9 pages

Practical Java Design Patterns Guide

The document describes five design patterns in software development: Singleton, Factory, Abstract Factory, Builder, and Prototype. Each pattern is illustrated with Java code examples that demonstrate their implementation and usage. These patterns help in creating efficient and maintainable code by managing object creation and relationships effectively.

Uploaded by

suresh
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

1.

Singleton Pattern

Ensures that a class has only one instance and provides a global access point to it.

class Singleton {
private static Singleton instance;

private Singleton() {}

public static Singleton getInstance() {


if (instance == null) {
instance = new Singleton();
}
return instance;
}

public void showMessage() {


[Link]("Singleton Instance");
}
}

public class SingletonDemo {


public static void main(String[] args) {
Singleton obj = [Link]();
[Link]();
}
}

Don’t forget to check the description- How to make this 100%


Singleton?
2. Factory Pattern

Provides an interface for creating objects, but allows subclasses to decide which class to
instantiate.

interface Shape {
void draw();
}

class Circle implements Shape {


public void draw() {
[Link]("Drawing a Circle");
}
}

class Rectangle implements Shape {


public void draw() {
[Link]("Drawing a Rectangle");
}
}

class ShapeFactory {
public static Shape getShape(String type) {
if ([Link]("CIRCLE")) {
return new Circle();
} else if ([Link]("RECTANGLE")) {
return new Rectangle();
}
return null;
}
}

public class FactoryDemo {


public static void main(String[] args) {
Shape shape1 = [Link]("CIRCLE");
[Link]();

Shape shape2 = [Link]("RECTANGLE");


[Link]();
}
}
3. Abstract Factory Pattern

Creates families of related objects without specifying their concrete classes.

interface Animal {
void makeSound();
}

class Dog implements Animal {


public void makeSound() {
[Link]("Bark");
}
}

class Cat implements Animal {


public void makeSound() {
[Link]("Meow");
}
}

abstract class AnimalFactory {


abstract Animal createAnimal();
}

class DogFactory extends AnimalFactory {


public Animal createAnimal() {
return new Dog();
}
}

class CatFactory extends AnimalFactory {


public Animal createAnimal() {
return new Cat();
}
}

public class AbstractFactoryDemo {


public static void main(String[] args) {
AnimalFactory dogFactory = new DogFactory();
Animal dog = [Link]();
[Link]();

AnimalFactory catFactory = new CatFactory();


Animal cat = [Link]();
[Link]();
}
}
4. Builder Pattern

Used to construct complex objects step by step.

class Car {
private String engine;
private int wheels;

private Car(CarBuilder builder) {


[Link] = [Link];
[Link] = [Link];
}

public static class CarBuilder {


private String engine;
private int wheels;

public CarBuilder setEngine(String engine) {


[Link] = engine;
return this;
}

public CarBuilder setWheels(int wheels) {


[Link] = wheels;
return this;
}

public Car build() {


return new Car(this);
}
}

public void showCar() {


[Link]("Car with Engine: " + engine + ", Wheels:
" + wheels);
}
}

public class BuilderDemo {


public static void main(String[] args) {
Car car = new
[Link]().setEngine("V8").setWheels(4).build();
[Link]();
}
}
5. Prototype Pattern

Creates new objects by copying an existing object, reducing the overhead of creating
complex objects.

import [Link];
import [Link];

abstract class Animal implements Cloneable {


public String name;

public abstract void makeSound();

public Animal clone() throws CloneNotSupportedException {


return (Animal) [Link]();
}
}

class Sheep extends Animal {


public Sheep() {
[Link] = "Sheep";
}

public void makeSound() {


[Link]("Baa Baa");
}
}

class PrototypeRegistry {
private static Map<String, Animal> registry = new HashMap<>();

static {
[Link]("Sheep", new Sheep());
}

public static Animal getClone(String type) throws


CloneNotSupportedException {
return [Link](type).clone();
}
}

public class PrototypeDemo {


public static void main(String[] args) throws
CloneNotSupportedException {
Animal clonedSheep = [Link]("Sheep");
[Link]();
}
}

Common questions

Powered by AI

Polymorphism is fundamental to the Factory and Abstract Factory Patterns, enabling these patterns to instantiate subclasses through a common interface without knowing or specifying the concreate classes they instantiate. In the Factory Pattern, polymorphism allows the creation of objects at runtime using a superclass interface, enabling the factory to decide the object class being created (e.g., Shape in the Factory Pattern) without altering the consuming code. In the Abstract Factory Pattern, it permits the creation of families of related objects through a common interface, such as AnimalFactory, which can generate various Animal subclasses like Dog or Cat . This abstraction supports scalability and adherence to the principle of programming to an interface rather than an implementation.

Prototypical inheritance, primarily used in languages like JavaScript, is a method of code reuse that allows objects to inherit properties and methods directly from other objects. It uses prototype chains instead of class-based inheritance to share behavior among objects. Meanwhile, the Prototype Pattern in software design is a creational pattern focused on cloning existing objects to create new instances, emphasizing the reuse of objects to avoid the performance cost of instantiation. While prototypical inheritance is a language feature for behavior sharing, the Prototype Pattern is a structured approach in object-oriented programming to optimize object creation by duplicating instances . These concepts, while both involving reuse, serve different purposes in design.

The Singleton Pattern ensures a class has only one instance by making the constructor private, preventing instance creation through direct invocation. It provides a static method, usually called getInstance(), to access the single instance. This method checks if the instance is null and, if so, initializes it. Once initialized, it returns the same instance on subsequent calls . To enforce singleton behavior, it is critical to ensure the instance creation is thread-safe and to prevent cloning or reflection from creating another instance.

The Builder Pattern constructs complex objects step by step by separating the construction process from the final representation. In this pattern, a class (CarBuilder) provides methods to configure and build the object's properties incrementally, such as setting the engine type and number of wheels. This promotes readability by allowing the client code to specify only the necessary configurations in a fluent interface style, resulting in clearer and more maintainable code. It also encapsulates object creation, preventing the client from dealing with complex constructors directly . This separation of concerns makes the code easier to manage and extend.

The primary distinction between the Factory Pattern and the Abstract Factory Pattern is their scope and flexibility in object creation. The Factory Pattern provides an interface for creating individual objects, allowing subclasses to determine which specific class to instantiate. In contrast, the Abstract Factory Pattern creates families of related or dependent objects without detailing their concrete classes, usually involving multiple factories to manage different types of products . This makes the Abstract Factory more suitable for situations where a system needs to be independent of its product creation process.

Thread-safety is crucial in the Singleton Pattern to ensure that only one instance is created even when multiple threads try to access the instance simultaneously. Without thread-safety, race conditions can occur, leading to the initialization of multiple instances. It can be achieved using synchronized methods, double-checked locking, or by using an inner static helper class to defer instance creation until it is needed. Double-checked locking is effective because it reduces the overhead of acquiring a lock by first checking the instance state without synchronization .

The Factory Design Pattern facilitates the addition of new products by using a central interface or method to instantiate objects, as seen in the ShapeFactory's getShape() method. This pattern centralizes object creation, allowing new product types (e.g., new Shape implementations) to be added with minimal changes. Developers can extend the factory to support new products by adding new classes that implement the interface (like Shape) and modifying the factory method to recognize these new types. This flexibility avoids modifying existing code, adhering to the Open-Closed Principle .

The Abstract Factory Pattern is preferable in scenarios where a system needs to be abstractly decoupled from its product creation process, such as in frameworks requiring families of related or dependent objects. It is ideal when a group of related functionalities must operate together within their family, and there is a need to ensure consistent use of these families of objects. Additionally, this pattern is beneficial when the application needs to be scalable, allowing easy integration of new product families without altering the client code . This promotes scalability and flexibility.

The Prototype Pattern is advantageous for object creation as it allows the creation of new objects by cloning an existing object, known as the prototype. This approach bypasses the overhead of repeatedly instantiating new objects, which can be costly in resource-intensive applications. By cloning existing objects, the pattern minimizes initialization time and complexity, especially for objects that have expensive construction processes or require costly resource acquisition . The use of a registry to store prototypical instances further enhances efficiency by providing easy access to clones with pre-existing state.

The Builder Pattern supports the creation of immutable objects by setting all properties of an object during its building phase before the object is actually constructed, as seen with the CarBuilder setting properties before invoking build(). Once created, the object, like Car, can inherently prevent any external modification to its state, thus maintaining immutability. Immutability in software design offers several benefits: it simplifies concurrent programming by eliminating the need for locking, enhances security by protecting the object's state from unauthorized modifications, and allows objects to be freely shared without risks of unforeseen side effects . Moreover, immutability leads to simpler and more predictable code, thus reducing potential bugs.

You might also like