0% found this document useful (0 votes)
2 views17 pages

Design Patterns Codes

The document provides an overview of various design patterns in software development, including the Observer, Factory, Singleton, Builder, Prototype, Strategy, and Decorator patterns. Each pattern is explained with its respective interfaces, classes, and client code examples in Java, highlighting their structure and benefits. The document emphasizes how these patterns improve code maintainability, scalability, and flexibility.
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)
2 views17 pages

Design Patterns Codes

The document provides an overview of various design patterns in software development, including the Observer, Factory, Singleton, Builder, Prototype, Strategy, and Decorator patterns. Each pattern is explained with its respective interfaces, classes, and client code examples in Java, highlighting their structure and benefits. The document emphasizes how these patterns improve code maintainability, scalability, and flexibility.
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

OBSERVER PATTERN

Step 1 — Observer Interface


java
interface Observer {
void update(double price); // common contract for all observers
}

Step 2 — Subject Interface


java
interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}

Step 3 — Concrete Subject


java
class Stock implements Subject {
private List<Observer> observers = new ArrayList<>();
private double price;

public void setPrice(double price) {


[Link] = price;
notifyObservers(); // just notify, don't care who's listening
}
// register / remove / notify implementations...
}

Step 4 — Concrete Observers


java
class MobileDisplay implements Observer {
public void update(double price) {
[Link]("Mobile: " + price);
}
}
class WebDisplay implements Observer {
public void update(double price) {
[Link]("Web: " + price);
}
}
Now adding a new display = just create a new class + register it. Zero changes to Stock.

Simple Coding Example (Java)


Let’s simulate a weather station 🌦️
1. Observer Interface
interface Observer {
void update(float temperature);
}

2. Subject Interface
interface Subject {
void addObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}

3. Concrete Subject (WeatherStation)


import [Link].*;

class WeatherStation implements Subject {


private List<Observer> observers = new ArrayList<>();
private float temperature;

public void setTemperature(float temp) {


[Link] = temp;
notifyObservers(); // notify when state changes
}

public void addObserver(Observer o) {


[Link](o);
}

public void removeObserver(Observer o) {


[Link](o);
}

public void notifyObservers() {


for (Observer o : observers) {
[Link](temperature);
}
}
}

4. Concrete Observer (Display Device)


class PhoneDisplay implements Observer {
public void update(float temperature) {
[Link]("Phone Display: Temperature updated to " + temperature);
}
}

5. Main Class
public class Main {
public static void main(String[] args) {
WeatherStation station = new WeatherStation();

Observer phone = new PhoneDisplay();

[Link](phone);

[Link](30.5f);
[Link](35.0f);
}
}

🧾 Output
Phone Display: Temperature updated to 30.5
Phone Display: Temperature updated to 35.0

FACTORY PATTERN

Good Design (With Factory Method Pattern)


Step 1 — Product Interface
java
public interface Report {
void generate(); // common contract for all reports
}

Step 2 — Concrete Products


java
public class PDFReport implements Report {
public void generate() { [Link]("Generating PDF"); }
}
public class WordReport implements Report {
public void generate() { [Link]("Generating Word"); }
}

Step 3 — Abstract Factory (Creator)


java
public abstract class ReportFactory {
public abstract Report createReport(); // subclasses decide what to create
}

Step 4 — Concrete Factories


java
public class PDFReportFactory extends ReportFactory {
public Report createReport() { return new PDFReport(); }
}
public class WordReportFactory extends ReportFactory {
public Report createReport() { return new WordReport(); }
}

Step 5 — Client Code


java
ReportFactory factory = new PDFReportFactory();
Report report = [Link]();
[Link](); // client never touches concrete classes

Step 1: Create Factory


ShapeFactory factory = new ShapeFactory();
👉 Factory object created

🔹 Step 2: Request Object


Shape s1 = [Link]("circle");

👉 Instead of:
new Circle()

➡️
We ask factory:​
“Give me a circle”

🔹 Step 3: Factory Decides


Inside factory:

if ([Link]("circle")) {
return new Circle();
}

👉 Factory creates object and returns it

🔹 Step 4: Use Object


[Link]();

👉 Calls method without caring about actual class

Shape Interface
interface Shape {
void draw();
}
👉 Common method for all shapes

2. Concrete Classes
class Circle implements Shape {
public void draw() {
[Link]("Drawing Circle");
}
}
class Rectangle implements Shape {
public void draw() {
[Link]("Drawing Rectangle");
}
}

👉 Different implementations of Shape

3. Factory Class (Main Logic 🔥)


class ShapeFactory {

public Shape getShape(String type) {


if (type == null) {
return null;
}

if ([Link]("circle")) {
return new Circle();
}
else if ([Link]("rectangle")) {
return new Rectangle();
}

return null;
}
}

👉 This is the core of Factory Pattern


●​ Takes input (circle, rectangle)
●​ Decides which object to create
●​ Returns it

💡 User doesn’t use new Circle() directly!

4. Main Class (Execution)


public class Main {
public static void main(String[] args) {

ShapeFactory factory = new ShapeFactory();

Shape s1 = [Link]("circle");
[Link]();

Shape s2 = [Link]("rectangle");
[Link]();
}
}

🧾 Output
Drawing Circle
Drawing Rectangle
SINGLETON PATTERN

The Singleton Class


java
public class AppConfig {
private static AppConfig instance; // step 1: private static instance
private AppConfig() { // step 2: private constructor
[Link]("Loading configuration...");
}

public static AppConfig getInstance() { // step 3: controlled access


if (instance == null) {
instance = new AppConfig(); // only created ONCE
}
return instance;
}

public String getDatabaseURL() {


return "jdbc:mysql://localhost/appdb";
}
}

Client Code
java
public class ModuleA {
AppConfig config = [Link](); // same object
}


public class ModuleB {
AppConfig config = [Link](); // same object
}

Both modules now share the exact same instance — loaded once, consistent
everywhere.

⚠️ Thread Safety Issue


In a multi-threaded environment, two threads could hit getInstance() at the
same time when instance is still null — creating two instances accidentally.

Fix — Synchronized Method


java
public static synchronized AppConfig getInstance() {
if (instance == null) {
instance = new AppConfig();
}
return instance;
}

The synchronized keyword ensures only one thread at a time can run this
method.

Trade-off: Slight performance overhead, but guarantees safety.

BUILDER PATTERN

Good Design (With Builder Pattern)


Step 1 — Main Class with Private Constructor
java
public class UserProfile {
private String username, email, phone, address; // fields

private UserProfile(Builder builder) { // only Builder can call this


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

Step 2 — Builder Class (lives inside UserProfile)


java
public static class Builder {
private String username, email; // mandatory
private String phone, address; // optional
public Builder(String username, String email) { // mandatory fields here
[Link] = username;
[Link] = email;
}

public Builder setPhone(String phone) {


[Link] = phone;
return this; // returns Builder for method chaining
}

public Builder setAddress(String address) {


[Link] = address;
return this;
}

public UserProfile build() {


return new UserProfile(this); // final step — create the object
}
}

Step 3 — Client Code


java
UserProfile profile = new [Link]("Ali", "ali@[Link]")
.setPhone("03001234567")
.setAddress("Karachi")


.setDateOfBirth("01-01-2000")
.build(); // clean, readable, step-by-step

PROTOTYPE PATTERN

ood Design (With Prototype Pattern)


Step 1 — Prototype Interface
java
public interface Prototype {
Prototype clone(); // every prototype must know how to copy itself
}

Step 2 — Concrete Prototype


java
public class Report implements Prototype {
private String title, headerStyle, chartType, dataFormat;

public Report(String headerStyle, String chartType, String dataFormat) {


[Link]("Heavy initialization... (runs ONCE)");
[Link] = headerStyle;
[Link] = chartType;
[Link] = dataFormat;
}

@Override
public Prototype clone() {


return new Report([Link], [Link], [Link]);
// copies config — NO heavy init repeated
}

public void setTitle(String title) { [Link] = title; }


}

Step 3 — Client Code


java
Report prototype = new Report("Modern", "Bar Chart", "PDF"); // init ONCE

Report report1 = (Report) [Link](); // fast copy ✅


[Link]("Sales Report");

Report report2 = (Report) [Link](); // fast copy ✅


[Link]("Finance Report");

Heavy initialization happens only once — all clones are instant.

⚠️ Shallow Copy vs Deep Copy


This is a critical concept in the Prototype Pattern.

Shallow Copy
java
// Both original and clone share the SAME address object


Employee clone = (Employee) [Link]();
// if [Link] changes → [Link] ALSO changes!

Deep Copy
java
// Clone gets its OWN independent copy of nested objects


Employee cloned = (Employee) [Link]();


[Link] = [Link](); // separate copy
// changes to clone don't affect original

Prototype Registry (Advanced)


For systems with many prototype types, store them in a central registry:

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

public static void addPrototype(String key, Prototype p) {


[Link](key, p);
}
public static Prototype getPrototype(String key) {
return [Link](key).clone(); // always returns a fresh clone
}
}

// Usage
[Link]("Financial", new Report("Classic", "Pie",


"Excel"));
Report r = (Report) [Link]("Financial"); // instant

Think of it as a template library — store once, clone anytime.


STRATEGY PATTERN

Bad Design (Before Pattern)


java
public class PaymentProcessor {
public void pay(String type, double amount) {
if ([Link]("CreditCard")) {
[Link]("Processing credit card...");
} else if ([Link]("PayPal")) {
[Link]("Processing PayPal...");
} else if ([Link]("BankTransfer")) {
[Link]("Processing bank transfer...");

😬
}
// add new method? modify this class AGAIN
}
}

Problems:

●​ Adding a new payment method = modifying this class every time


●​ Violates Open-Closed Principle
●​ Hard to read, hard to test
●​ All behaviors tightly coupled in one place
●​ Grows uncontrollably as system evolves

✅ Good Design (With Strategy Pattern)


Step 1 — Strategy Interface
java
public interface PaymentStrategy {
void pay(double amount); // common contract for all payment methods
}

Step 2 — Concrete Strategies (one class per behavior)


java
public class CreditCardPayment implements PaymentStrategy {
public void pay(double amount) {
[Link]("Paid " + amount + " using Credit Card");
}
}
public class PayPalPayment implements PaymentStrategy {
public void pay(double amount) {
[Link]("Paid " + amount + " using PayPal");
}
}
public class BankTransferPayment implements PaymentStrategy {
public void pay(double amount) {
[Link]("Paid " + amount + " using Bank Transfer");
}
}

Step 3 — Context Class


java
public class PaymentProcessor {
private PaymentStrategy strategy; // holds whichever strategy is active


public void setStrategy(PaymentStrategy strategy) {
[Link] = strategy; // swap strategy at runtime
}
public void processPayment(double amount) {
[Link](amount); // delegates to the active strategy
}
}

Step 4 — Client Code


java
PaymentProcessor processor = new PaymentProcessor();

[Link](new CreditCardPayment());
[Link](5000); // Paid 5000 using Credit Card

[Link](new PayPalPayment());
[Link](3000); // Paid 3000 using PayPal

Adding a new payment method? Just create a new class — zero changes to
existing code.

DECORATOR PATTERN

❌ Bad Design (Before Pattern)


SimpleCoffee
CoffeeWithMilk
CoffeeWithSugar
CoffeeWithMilkAndSugar
CoffeeWithChocolate
CoffeeWithChocolateAndMilk

😬
CoffeeWithChocolateAndMilkAndSugar
...

Problems:

●​ Class count explodes with every new feature


●​ Every new combination = a brand new class
●​ Massive code duplication
●​ Impossible to maintain or scale

✅ Good Design (With Decorator Pattern)


Step 1 — Component Interface
java
interface Coffee {
double getCost();
String getDescription();
}

Step 2 — Concrete Component (the base object)


java
class SimpleCoffee implements Coffee {
public double getCost() { return 100; }
public String getDescription() { return "Simple Coffee"; }
}

Step 3 — Abstract Decorator


java
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee; // holds reference to wrapped object

public CoffeeDecorator(Coffee coffee) {


[Link] = coffee; // wraps whatever Coffee is passed in
}
}

Step 4 — Concrete Decorators


java
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) { super(coffee); }

public double getCost() { return [Link]() + 30; }


public String getDescription() { return [Link]() + ", Milk"; }
}

class SugarDecorator extends CoffeeDecorator {


public SugarDecorator(Coffee coffee) { super(coffee); }

public double getCost() { return [Link]() + 20; }


public String getDescription() { return [Link]() + ", Sugar"; }
}

Step 5 — Client Code


java
Coffee coffee = new SimpleCoffee(); // cost: 100
coffee = new MilkDecorator(coffee); // cost: 130
coffee = new SugarDecorator(coffee); // cost: 150

[Link]([Link]()); // Simple Coffee, Milk, Sugar


[Link]([Link]()); // 150.0
🔍 How the Wrapping Works
Each decorator calls the inner object's method first, then adds its own on top:

[Link]()
→ calls [Link]()
→ calls [Link]() → 100


→ adds 30 (milk) → 130
→ adds 20 (sugar) → 150

Think of it like peeling an onion — each layer adds its piece, delegating the rest
inward.

You might also like