UML Class Relationships and Single Responsibility Principle Implementation

UML Class Diagrams: Types of Class Relationships

In object-oriented design, classes interact through various relationships. These relationships define how objects communicate and depend on each other within a system.

1. Association

Association represents a "uses-a" relationship where objects know about each other. It includes:

  • Unidirectional Association: One class knows about another, but not vice versa.
  • Bidirectional Association: Both classes are aware of each other.
  • Self-Association: A class associates with itself (e.g., an employee managing other employees).
  • Multiplicity: Defines cardinality (1:1, 1:N, N:M).
  • Aggregation: A weak "has-a" relationship where the child can exist independently.
  • Composition: A strong "has-a" relationship where the child cannot exist without the parent.

2. Generalization (Inheritance)

Represents an "is-a" relationship where a subclass inherits attributes and methods from a parent class.

3. Dependency

A relationship where one class depends on another, typically as a method parameter or local variable. Changes to the supplier may affect the client.

Single Responsibility Principle: Login Module Implementation

The Single Responsibility Principle (SRP) states that a class should have only one reason to change. A login module can be refactored to separate concerns: database operations, user interface, and authentication logic.

DatabaseConnection.java

package authentication.module;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DatabaseConnection {
    
    private static final String DB_URL = "jdbc:mysql://localhost:3306/app_db?serverTimezone=UTC&useSSL=false";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "password";
    
    private DatabaseConnection() {}
    
    public static Connection establishConnection() {
        Connection connection = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
        } catch (ClassNotFoundException | SQLException e) {
            System.err.println("Database connection failed: " + e.getMessage());
        }
        return connection;
    }
    
    public static void terminateConnection(ResultSet resultSet, Statement statement, Connection connection) {
        closeResultSet(resultSet);
        closeStatement(statement);
        closeConnection(connection);
    }
    
    private static void closeResultSet(ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                System.err.println("Failed to close ResultSet: " + e.getMessage());
            }
        }
    }
    
    private static void closeStatement(Statement statement) {
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                System.err.println("Failed to close Statement: " + e.getMessage());
            }
        }
    }
    
    private static void closeConnection(Connection connection) {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                System.err.println("Failed to close Connection: " + e.getMessage());
            }
        }
    }
}

UserRepository.java

package authentication.module;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class UserRepository {
    
    public boolean authenticateUser(String userId, String userPassword) {
        String query = "SELECT password FROM users WHERE username = '" + userId + "'";
        Connection connection = DatabaseConnection.establishConnection();
        Statement statement = null;
        ResultSet resultSet = null;
        
        try {
            statement = connection.createStatement();
            resultSet = statement.executeQuery(query);
            
            if (resultSet.next()) {
                String storedPassword = resultSet.getString("password");
                return userPassword.equals(storedPassword);
            }
            return false;
        } catch (SQLException e) {
            System.err.println("Authentication query failed: " + e.getMessage());
            return false;
        } finally {
            DatabaseConnection.terminateConnection(resultSet, statement, connection);
        }
    }
}

LoginView.java

package authentication.module;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class LoginView extends JFrame {
    
    private JTextField userIdField;
    private JPasswordField passwordField;
    private UserRepository userRepository;
    
    public LoginView() {
        this.userRepository = new UserRepository();
        initializeComponents();
        configureLayout();
    }
    
    private void initializeComponents() {
        setTitle("User Authentication");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setLocationRelativeTo(null);
        setSize(450, 250);
    }
    
    private void configureLayout() {
        JPanel panel = new JPanel();
        panel.setLayout(null);
        
        JLabel userLabel = new JLabel("Username:");
        userLabel.setBounds(50, 50, 80, 25);
        panel.add(userLabel);
        
        userIdField = new JTextField();
        userIdField.setBounds(140, 50, 200, 25);
        panel.add(userIdField);
        
        JLabel passwordLabel = new JLabel("Password:");
        passwordLabel.setBounds(50, 100, 80, 25);
        panel.add(passwordLabel);
        
        passwordField = new JPasswordField();
        passwordField.setBounds(140, 100, 200, 25);
        panel.add(passwordField);
        
        JButton loginButton = new JButton("Sign In");
        loginButton.setBounds(100, 160, 100, 30);
        loginButton.addActionListener(new LoginActionListener());
        panel.add(loginButton);
        
        JButton resetButton = new JButton("Clear");
        resetButton.setBounds(220, 160, 100, 30);
        resetButton.addActionListener(e -> resetFields());
        panel.add(resetButton);
        
        add(panel);
        setVisible(true);
    }
    
    private void resetFields() {
        userIdField.setText("");
        passwordField.setText("");
    }
    
    private class LoginActionListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            String username = userIdField.getText().trim();
            String password = new String(passwordField.getPassword()).trim();
            
            if (username.isEmpty() || password.isEmpty()) {
                JOptionPane.showMessageDialog(null, "All fields are required", "Validation Error", JOptionPane.WARNING_MESSAGE);
                return;
            }
            
            boolean isAuthenticated = userRepository.authenticateUser(username, password);
            
            if (isAuthenticated) {
                JOptionPane.showMessageDialog(null, "Authentication successful!", "Success", JOptionPane.INFORMATION_MESSAGE);
            } else {
                JOptionPane.showMessageDialog(null, "Invalid credentials", "Authentication Failed", JOptionPane.ERROR_MESSAGE);
            }
        }
    }
}

Application.java

package authentication.module;

public class Application {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(LoginView::new);
    }
}

The refactored design separates responsibilities into three distinct classes:

  • DatabaseConnection: Manages database connectivity and resource cleanup.
  • UserRepository: Handles data access and authentication queries.
  • LoginView: Manages the user interface and user interactions.

Tags: UML Object-Oriented Design Single Responsibility Principle java Design Patterns

Posted on Thu, 07 May 2026 14:08:19 +0000 by jenniferG