CSCI 370 Lecture 12: Design Principles, Software Process Models, and the Singleton & Factory Patterns


βœ… Key Topics Covered


πŸ” Functional vs. Non-Functional Requirements

Functional Requirements describe what the system should do, i.e., the features and functionalities requested by the user or client.

Non-Functional Requirements describe how the system performs a function, covering broader system attributes like performance, usability, reliability, etc. They often span multiple functional requirements.

Example: A system must process user logins (functional) and must do so within 2 seconds (non-functional).


🌩️ Cloud Software Benefits

Correct answer to the multiple-choice example: All of the above


🧠 Design Principles

Composition Over Inheritance

Example: A MedicalRecord class contains a Database object => Composition (β€œhas-a”)

Open/Closed Principle


πŸ§ͺ Incremental Development and Agile Models

Incremental development includes:

Models not using incremental development:


✈️ When to Use the Waterfall Model

Used when changes are expensive or difficult after development begins. Examples:

Reasons:

Not suitable for:


🧬 UML and Object-Oriented Relationships

Types of Relationships:

Examples:


βš™οΈ Singleton Pattern (Java Implementation)

Problem Being Solved

Solution: Singleton Pattern

Purpose

Two Forms of Singleton

1. Eager Initialization

private static NextId instance = new NextId();

2. Lazy Initialization

private static DatabaseConnection connection = null;
 
public static DatabaseConnection getConnection() {
    if (connection == null) {
        connection = new DatabaseConnection();
    }
    return connection;
}

Common Issue: Thread Safety


🏭 Factory Pattern (Java Implementation)

Purpose

Benefits

Example from Class

public Bicycle getNewBicycle(int age) {
    if(age < 6)
        return new KidsTriCycle();
    if(age < 19)
        return new TenSpeedBicycle();
    return new MotorCycle();
}

Java Usage

Bicycle bicycle = new BicycleFactory().getNewBicycle(6);
bicycle.ride();

πŸ‘οΈ Observer Pattern

Purpose

Benefit

Example

interface Observer {
    void notify();
}

🧩 Strategy Pattern

Purpose

Principle

Example

Duck d = new Duck(new RealFly(), new LoudQuack());

🧭 Software Project Lifecycle Phases (Correct Order)

  1. Feasibility Study – Can it be built within budget/tech constraints?
  2. Requirements – Define what the system should do
  3. Design – Architecting system components
  4. Development – Actual coding
  5. Testing – Verify correctness and reliability
  6. (Optional) Deployment, Maintenance

πŸ” Reusability and Maintainability


πŸ‘¨β€πŸ’» Software Engineering Essentials


πŸ“‹ Summary of Design Patterns Covered

PatternPurposeBenefit
SingletonOne instance only; global controlPrevents uncontrolled access to shared resource
FactoryEncapsulate object creationEasy, centralized, controlled instantiation
ObserverNotify multiple dependent objects on state changeLoose coupling, unified notification interface
StrategyBehavior injection using compositionFlexible, avoids inheritance problems

πŸ’¬ Interview Tips


πŸ”š Summary

This lecture focused on core design principles and the practical implications of software development models. Key design patterns like Singleton, Factory, Observer, and Strategy help implement robust, modular, and maintainable systems. Singleton prevents issues with shared state, Factory simplifies object creation, Observer supports publish-subscribe architecture, and Strategy encourages behavior flexibility. Understanding when and how to apply these patterns is essential for real-world software engineering.