1. Tight Coupling
LogisticsService depends directly on the concrete classes Air and Road.
- The Issue: The high-level service (the one that runs the delivery) knows exactly how to build the low-level transport objects.
- The Impact: If you rename a class, change a constructor, or delete a transport mode, you must also edit
LogisticsService.
2. Violation of the Open/Closed Principle (OCP)
Code should be open for extension (you can add to it) but closed for modification (you do not edit what already works).
- The Issue: Each new transport mode (e.g.,
Sea,Rail,Drone) means openingLogisticsService.javaand adding anotherelse-ifblock. - The Impact: Every new delivery option puts your core service logic at risk of breaking.
3. "God Method" Logic
The send(String mode) method does two separate jobs. This breaks the Single Responsibility Principle, which says a unit of code should have one job.
- Responsibility 1: Deciding which object to create (Creation Logic).
- Responsibility 2: Executing the business logic (
logistics.send()). - The Impact: As the application grows, this method turns into a huge block of conditions that is hard to unit test.
4. Brittle String Comparisons
The code picks the class with raw string comparisons like mode.equals("Air").
- The Issue: A small typo (e.g.,
"air"vs"Air") or a changed naming style makes the request miss every branch. Theif-elsehas no finalelse, so the service silently does nothing and no error is raised. - The Impact: The compiler cannot check that the requested mode exists or is handled.
Summary
The new keyword is useful, but inside business logic it ties your code to one concrete class (a "Concrete Dependency"). The Factory Pattern (here a Simple Factory) fixes this by moving new out of the service and into a dedicated factory class.