project statement: link +
This project is a comprehensive example of a User Subscription Management System built with modern Java. It serves as a practical demonstration of core software engineering principles, including Object-Oriented Programming (OOP), SOLID principles, Design Patterns, and the effective use of modern Java features.
The project has evolved through two main versions:
- v1.0.0: The foundational system focusing on core subscription management (
Customer,Service,Subscription). - v2.0.0: An enhanced version that introduces new entities (
Invoice,Payment,Notification) and demonstrates advanced object creation patterns (Builder, Factory).
- Customer & Service Management: Create and manage system users and services.
- Subscription Lifecycle: Subscribe a customer to a service and cancel an existing subscription.
- Advanced Reporting: List active subscriptions, find services for a customer, and identify customers for a service.
- Billing System: Introduces
InvoiceandPaymententities to simulate a billing cycle. - Notification System: A
NotificationFactoryto create and send different types of notifications (Email, SMS). - Advanced Object Creation: Demonstrates Builder, Factory, Constructor, and Setter patterns for creating objects.
This project was built with a strong emphasis on clean code and robust architecture.
- Encapsulation: The internal state of objects is hidden and can only be modified through public methods.
- Abstraction: The
ISubscriptionManagerinterface provides an abstract view of the system's capabilities. - Polymorphism: The
Notificationinterface allows different notification types to be treated uniformly.
- (S) Single Responsibility Principle: Each class has a single, well-defined purpose.
- (O) Open/Closed Principle: The system is open for extension (e.g., new
Notificationtypes) but closed for modification. - (L) Liskov Substitution Principle: Any implementation of
ISubscriptionManagercan be substituted for another. - (I) Interface Segregation Principle:
ISubscriptionManagerdefines a clear contract for subscription-related operations. - (D) Dependency Inversion Principle: High-level modules (
Main) depend on abstractions (ISubscriptionManager), not on concrete implementations.
- Singleton Pattern (v1.0.0+):
SubscriptionManagerensures only one instance manages the application's data. - Builder Pattern (v2.0.0): Used in the
Customerclass for readable and flexible object creation. - Factory Pattern (v2.0.0):
NotificationFactorycreates notification objects without exposing instantiation logic to the client.
- Stream API & Lambda Expressions: Used extensively for querying and processing data collections.
- Records (v1.0.0):
CustomerandServicewere initially implemented as records for immutable data transfer. - Local-Variable Type Inference (
var): Reduces verbosity while maintaining strong type safety. List.of()&toList(): Creates unmodifiable lists to enhance data safety.
src/
└── com/
└── subscription/
├── model/
│ ├── Customer.java # Class with a Builder
│ ├── Service.java # Record
│ ├── Subscription.java
│ ├── Invoice.java # Constructor creation
│ └── Payment.java # Setter creation
├── notification/
│ ├── Notification.java # Interface for Factory Pattern
│ ├── EmailNotification.java
│ ├── SmsNotification.java
│ ├── NotificationType.java
│ └── NotificationFactory.java # The Factory
├── service/
│ └── ISubscriptionManager.java # The service contract
├── service/impl/
│ └── SubscriptionManager.java # The core logic
└── Main.java # Application entry point
You can compile and run this project from the command line using the Java Development Kit (JDK).
-
Navigate to the Source Directory: Open your terminal and change the directory to the
srcfolder.cd path/to/your/project/src -
Compile the Java Files: Compile all
.javafiles. The-d .flag places the compiled.classfiles in the current directory while respecting the package structure.javac -d . com/subscription/**/*.java
-
Run the Application: Execute the
mainmethod in thecom.subscription.Mainclass.java com.subscription.Main
This project uses Git tags to mark stable versions. You can easily switch between v1.0.0 and v2.0.0 to see the project's evolution.
If you have been committing your changes, you can find the commit hash for each version and tag it.
-
Find the commit hash for the first version (where you only had the basic subscription management).
git log
Copy the commit hash (e.g.,
a1b2c3d). -
Tag the first version.
git tag -a v1.0.0 a1b2c3d -m "Version 1.0.0: Core subscription management system" -
Find the commit hash for the second version (with invoices, payments, and creation patterns).
git log
Copy the commit hash (e.g.,
e4f5g6h). -
Tag the second version.
git tag -a v2.0.0 e4f5g6h -m "Version 2.0.0: Added billing, notifications, and creation patterns" -
(Optional) Push tags to your remote repository.
git push origin --tags
You can use git checkout to switch to any tagged version. This will change the files in your working directory to match that version's state.
-
Switch to Version 1.0.0:
git checkout v1.0.0
Your project files will now reflect the initial, simpler version. You can explore the code and run it as it was then.
-
Switch to Version 2.0.0:
git checkout v2.0.0
This will bring you to the latest version with all the enhancements.
-
Return to the Latest Work: To go back to your main development branch (e.g.,
mainormaster), use:git checkout main