Java and Object-Oriented Design Fundamentals
AntraSoftware Engineer · Technical ScreenLast updated
This problem tests your understanding of interface design, the Liskov Substitution Principle, and proper usage of Java Collections in a Spring-managed context.
Task: Implement a Payment Strategy Pattern in Spring
You are building a payment processing system for an e-commerce platform. Your task is to design a system that supports multiple payment methods (e.g., Credit Card, PayPal, Crypto) while ensuring the code is extensible and adheres to SOLID principles.
Requirements:
- Define a generic
PaymentStrategyinterface with aprocessPayment(double amount)method. - Create two concrete implementations:
CreditCardPaymentandCryptoPayment. - Create a
PaymentServiceclass that uses aMapto store strategies. Use Spring's dependency injection to automatically populate this map with all available strategy beans. - Add a method
executePayment(String type, double amount)to thePaymentServicethat retrieves the correct strategy from the map and processes the payment. If the type is unknown, throw anIllegalArgumentException.
Considerations:
- How do you ensure that adding a new payment method does not require modifying the existing
PaymentServicelogic (Open/Closed Principle)? - Why might you choose a
Mapover a longif-elseorswitchstatement? - How does Spring's
@Qualifieror bean autowiring facilitate this pattern?
Example Usage:
// Assume these beans are managed by Spring
PaymentService service = ...;
// Should look up the 'creditCard' bean and call processPayment(100.0)
service.executePayment("creditCard", 100.0);
Hints
Hint 1
Use Spring's ability to inject all implementations of an interface into a List or Map by adding them to the constructor of the service.
Hint 2
Think about how to map specific identifiers (like strings) to bean instances to avoid hard-coding logic.
Hint 3
Review the Liskov Substitution Principle: ensure your concrete implementations do not change the expected behavior or throw unexpected exceptions that the base interface doesn't account for.
Follow-up questions
- How would you handle the scenario where one payment method requires a different set of input parameters than another?
- What are the trade-offs of using field injection vs. constructor injection for the strategy map?
- How would you implement thread safety if the payment strategies were required to hold state during the transaction?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.