CACS354 Advance Java Programming

Advance Java ProgrammingUnit 318 min read

JavaBeans & Design Patterns: Components, Properties & Architectural Patterns

Unit 3 of Advanced Java Programming introduces JavaBeans (reusable components with properties, events, and persistence) and design patterns (proven solutions to common software design problems), with hands-on examples, comparisons, and real-world applications in enterprise Java development.

TAKEAWAYS:

  • JavaBeans are serializable, reusable components with properties, events, and customizable behavior, enabling modularity in GUI and web apps.
  • Properties (bound, constrained, indexed) allow dynamic data binding and validation, while introspection enables runtime reflection.
  • Design patterns (Singleton, Factory, Observer, etc.) solve recurring problems like object creation, state management, and loose coupling.
  • Patterns like MVC (Model-View-Controller) and Strategy are widely used in frameworks (Spring, Jakarta EE) and apps (eSewa’s transaction handling).
  • Persistence in JavaBeans is achieved via serialization or external storage (XML/JSON), critical for saving state in distributed systems.
  • Exam focus: Define terms, compare patterns, and explain how JavaBeans integrate with GUI/database systems (e.g., NTC’s ticketing system).

1. JavaBeans: The Building Blocks of Reusable Components

JavaBeans are lightweight, reusable software components that follow specific conventions to enable introspection (runtime inspection of properties/methods) and event handling. They are widely used in GUI development (Swing/JSP), enterprise applications, and configuration systems.

Key Characteristics of JavaBeans

A valid JavaBean must adhere to:

  1. Public no-arg constructor (for instantiation).
  2. Properties (getter/setter methods for private fields).
  3. Serializable (to save/restore state).
  4. Event support (optional, for listener-based interactions).
classDiagram
    class JavaBean {
        +String name
        +int age
        +void setName(String name)
        +String getName()
        +void setAge(int age)
        +int getAge()
    }
    JavaBean : "1. Public no-arg constructor (omitted but implied)"
    JavaBean : "2. Properties with getters/setters"
    JavaBean : "3. Serializable (interface, not shown)"
    JavaBean : "4. Event support (optional, not depicted)"
    note for JavaBean
        This diagram omits the no-arg constructor (assumed) and event support (not standard).
        Serializable is an interface, not a method.

Properties in JavaBeans

Properties define the state of a JavaBean. They are categorized into:

private String route;0private double price;1private int seatsAvailable;2
Private fields in a TicketBean with corresponding getters/setters (example)
Type Definition Example Use Case
Bound Notifies listeners when the value changes (e.g., PropertyChangeListener). name property in a UserBean. Dynamic UI updates (e.g., eSewa balance display).
Constrained Validates changes before applying (e.g., VetoableChangeListener). age must be ≥18. Form validation (e.g., Daraz checkout).
Indexed Array-like properties (e.g., getItem(int index)). products[] in an InventoryBean. Managing collections (e.g., NTC ticket queues).

Example: A BankAccountBean with Bound Property

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class BankAccountBean {
    private double balance;
    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);

    public double getBalance() {
        return balance;
    }

    public void setBalance(double newBalance) {
        double oldBalance = balance;
        balance = newBalance;
        pcs.firePropertyChange("balance", oldBalance, newBalance);
    }

    public void addListener(PropertyChangeListener listener) {
        pcs.addPropertyChangeListener(listener);
    }
}

Trace: Balance Update with Listener

Step Action State Change Listener Notification
1 account.addListener(listener) Listener registered. —
2 account.setBalance(1000) balance → 1000 Fires PropertyChangeEvent with old=0, new=1000.

Visualization: Bound Property in Action

    [Listener] <--> [BankAccountBean]
    (onPropertyChange)       (fireEvent)

When balance changes, listeners (e.g., a GUI panel) update automatically.

Persistence in JavaBeans

JavaBeans persist state via:

  1. Serialization (built-in Java mechanism to save/load objects).
  2. External Storage (XML/JSON for human-readable data).

Example: Serializing a UserBean

import java.io.*;

public class UserBean implements Serializable {
    private String username;
    private transient String password; // Not serialized

    // Getters/setters...
}

public class PersistenceDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        UserBean user = new UserBean();
        user.setUsername("admin");

        // Serialize
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.dat"))) {
            oos.writeObject(user);
        }

        // Deserialize
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.dat"))) {
            UserBean loadedUser = (UserBean) ois.readObject();
            System.out.println("Loaded username: " + loadedUser.getUsername());
        }
    }
}

Output:

Loaded username: admin

Advantages of JavaBeans

Advantage Explanation
Reusability Components can be reused across projects (e.g., PaymentBean in eSewa/Khalti).
Introspection Tools (e.g., IDEs) can inspect properties/methods at runtime.
Event-Driven Supports listener patterns for dynamic interactions.
Serialization State can be saved/loaded easily (e.g., NTC’s user preferences).
Loose Coupling Beans interact via interfaces, not direct dependencies.

Disadvantages

  • Verbose code (boilerplate getters/setters).
  • Performance overhead (introspection adds runtime checks).

2. Design Patterns: Solving Recurring Problems

Design patterns are template solutions to common software design challenges. They promote code reuse, maintainability, and scalability. Below are key patterns with real-world ties.

Creational Patterns: Object Instantiation

Pattern Problem Solution Example in Nepal
Singleton Ensure only one instance exists. Private constructor + static instance. DatabaseConnection (shared across NTC apps).
Factory Delegate instantiation to a factory. Factory method or abstract factory. PaymentGatewayFactory (eSewa/Khalti switch).
Builder Construct complex objects step-by-step. Separate builder class from product. OrderBuilder in Daraz (customize product options).

Example: Singleton Pattern (Database Connection)

public class DatabaseConnection {
    private static DatabaseConnection instance;
    private DatabaseConnection() {} // Private constructor

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

Trace: Thread-Safe Singleton

Thread 1 Thread 2
getInstance() called getInstance() called
Checks instance == null → true Checks instance == null → true
Creates new instance Race condition: Both threads create instances!

Fix: Use synchronized or double-checked locking:

public static DatabaseConnection getInstance() {
    if (instance == null) { // First check (non-synchronized)
        synchronized (DatabaseConnection.class) {
            if (instance == null) { // Second check (synchronized)
                instance = new DatabaseConnection();
            }
        }
    }
    return instance;
}

Structural Patterns: Class/Object Composition

Pattern Problem Solution Example in Nepal
Adapter Make incompatible interfaces work. Wrapper class converts interface A to B. LegacyPaymentGatewayAdapter for old NTC systems.
Decorator Add responsibilities dynamically. Wrap object in decorator classes. PremiumUserDecorator in Pathao (extra features).
Facade Simplify complex subsystem access. Single interface hides complexity. NTCTicketFacade (hides queue/booking logic).
adaptsdecoratesprovidesPaymentGatewayLegacyNTCPremiumDecoratorUser
Class composition relationships in structural patterns

Example: Decorator Pattern (Pathao Premium Features)

classDiagram
    class Ride {
        <<abstract>>
        +double calculateCost()
    }
    class BasicRide {
        +calculateCost(): double
    }
    class PremiumRide {
        +Ride ride
        +calculateCost(): double
    }
    PremiumRide : "extends Ride"
    PremiumRide --> Ride : "decorates"
interface Ride {
    double calculateCost();
}

class BasicRide implements Ride {
    @Override
    public double calculateCost() { return 100; }
}

class PremiumRideDecorator implements Ride {
    private final Ride ride;

    public PremiumRideDecorator(Ride ride) {
        this.ride = ride;
    }

    @Override
    public double calculateCost() {
        return ride.calculateCost() * 1.2; // 20% premium
    }
}

Trace: Cost Calculation

Step Action Cost Calculation
1 Ride basicRide = new BasicRide() basicRide.calculateCost() → 100
2 Ride premiumRide = new PremiumRideDecorator(basicRide) —
3 premiumRide.calculateCost() 100 * 1.2 → 120

Behavioral Patterns: Object Interaction

Pattern Problem Solution Example in Nepal
Observer Notify multiple objects of changes. Subject maintains list of observers. StockPriceObserver (NEPSE updates).
Strategy Swap algorithms at runtime. Encapsulate algorithms in separate classes. PaymentStrategy (eSewa/Khalti/Debit Card).
MVC Separate UI, logic, and data. Model (data), View (UI), Controller (logic). UserDashboard in NTC’s mobile app.

Example: Observer Pattern (NEPSE Stock Updates)

interface Observer {
    void update(String stockName, double price);
}

class StockMarket {
    private List<Observer> observers = new ArrayList<>();
    private String stockName;
    private double price;

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void setPrice(double price) {
        this.price = price;
        notifyObservers();
    }

    private void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(stockName, price);
        }
    }
}

class StockApp implements Observer {
    @Override
    public void update(String stockName, double price) {
        System.out.println(stockName + ": ₹" + price);
    }
}

Trace: NEPSE Update Notification

Step Action Output
1 StockMarket market = new StockMarket(); —
2 market.addObserver(new StockApp()); Observer registered.
3 market.setPrice(150.50); NEPSE: ₹150.50 (printed to console).

3. JavaBeans + Design Patterns: A Real-World Integration

Scenario: NTC’s Ticket Booking System

  • JavaBean: TicketBean (properties: route, price, seatsAvailable).
  • Design Pattern: Observer (notify users when seats are available).
  • Persistence: Serialize TicketBean to save booking data.
classDiagram
    class TicketBean {
        +String route
        +double price
        +int seatsAvailable
        +addObserver(Observer)
        +setSeatsAvailable(int)
    }
    class NTCBookingSystem {
        +TicketBean ticket
        +Observer user1
        +Observer user2
    }
    NTCBookingSystem --> TicketBean : "contains"
    TicketBean --> Observer : "notifies"

Code Example: NTC Ticket Observer

class NTCBookingSystem {
    private TicketBean ticket = new TicketBean("Kathmandu-Pokhara", 500, 100);

    public void addUser(Observer user) {
        ticket.addObserver(user);
    }

    public void bookTicket(int seats) {
        int newSeats = ticket.getSeatsAvailable() - seats;
        ticket.setSeatsAvailable(newSeats);
    }
}

public class Main {
    public static void main(String[] args) {
        NTCBookingSystem system = new NTCBookingSystem();
        system.addUser(new Observer() {
            @Override
            public void update(String route, int availableSeats) {
                System.out.println("Available seats for " + route + ": " + availableSeats);
            }
        });
        system.bookTicket(10); // Notifies observers
    }
}

Output:

Available seats for Kathmandu-Pokhara: 90

In the Real World

  1. eSewa/Khalti: Factory Pattern for Payment Gateways

    • Idea: The Factory Pattern dynamically selects the payment method (eSewa, Khalti, Credit Card) based on user choice.
    • How: A PaymentGatewayFactory creates the appropriate PaymentProcessor (e.g., eSewaProcessor or KhaltiProcessor) without exposing instantiation logic.
    • Example: When a user selects "Pay with eSewa," the factory returns an eSewaProcessor instance, which handles the transaction.
  2. Daraz: Observer Pattern for Order Status

    • Idea: The Observer Pattern keeps customers updated on their order status (processing, shipped, delivered).
    • How: The Order class (subject) maintains a list of OrderStatusListeners (observers). When the order state changes (e.g., "shipped"), the Order notifies all listeners.
    • Example: A customer’s app receives a push notification: "Your Daraz order #12345 is out for delivery!"
  3. NTC Ticketing System: Singleton + Decorator

    • Idea: The Singleton Pattern ensures only one TicketDatabase instance exists (shared across all NTC apps). The Decorator Pattern adds premium features (e.g., priority seating) dynamically.
    • How: A BasicTicket is wrapped in a PremiumTicketDecorator, which adds extra charges and priority handling.
    • Worked Example:
      • A user books a Basic Ticket (₹500).
      • The system wraps it in a PremiumDecorator, increasing the price to ₹600 and guaranteeing a seat near the front.

Exam Tip: How to Score Full Marks

  1. Define Terms Clearly

    • For JavaBeans: Always mention properties, introspection, serialization, and event support.
    • For patterns: Name the problem, solution, and real-world analogy (e.g., "Singleton ensures one database connection like NTC’s shared server").
  2. Draw Diagrams for Patterns

    • UML Class Diagrams for creational/structural patterns (e.g., Factory, Decorator).
    • Sequence Diagrams for behavioral patterns (e.g., Observer, MVC).
    • Example:
      sequenceDiagram
          participant User
          participant NTCApp
          participant TicketBean
          participant Observer
          User->>NTCApp: Book Ticket
          NTCApp->>TicketBean: setSeatsAvailable(90)
          TicketBean->>Observer: notify("Kathmandu-Pokhara: 90 seats left")
  3. Compare Patterns in Tables

    • Use a comparison table for 2–3 patterns (e.g., Singleton vs. Factory vs. Builder). Highlight:
      • When to use each.
      • Pros/cons (e.g., Singleton is simple but hard to test; Factory is flexible but complex).
  4. Show Code + Trace

    • For JavaBeans: Include a serialization example and trace property changes.
    • For patterns: Provide a short code snippet (5–7 lines) and a step-by-step trace table.
  5. Link to Real Scenarios

    • Always tie answers to Nepalese apps (eSewa, NTC, Daraz) or global examples (Google Maps uses Singleton for maps; WhatsApp uses Observer for message updates).
    • Example answer structure:

      "In NTC’s ticketing system, the Observer Pattern is used to notify users when seats become available. The TicketBean acts as the subject, while user apps are observers. When seats are booked, TicketBean fires an event, and observers (e.g., a waiting list app) update dynamically."

  6. Avoid Common Mistakes

    • ❌ Forgetting "serializable" in JavaBean definitions.
    • ❌ Mixing up bound/constrained properties (bound = notify; constrained = validate).
    • ❌ Describing patterns without code (examiners expect pseudocode or Java snippets).

Final Checklist Before Exam

  • Can I define JavaBean + list its 4 key traits?
  • Can I draw a UML diagram for Singleton/Observer/Decorator?
  • Can I write 5 lines of code for a Factory or Observer pattern?
  • Can I trace a JavaBean property change with listeners?
  • Can I compare 2 design patterns in a table?
  • Can I explain how eSewa/Khalti uses Factory or NTC uses Observer?

Based on the TU BCA syllabus for Advance Java Programming (CACS354), unit 3.

Discussion

Loading…