mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-21 02:24:21 +00:00
feat: Money pattern (#3109)
* Money pattern the implementation of the money patter and the tests along with the read me file * Update money/README.md Co-authored-by: Ilkka Seppälä <iluwatar@users.noreply.github.com> * added App file anf modified README file and pom.xml file * modified README and pom.xml * added comments * Added a test for App.java --------- Co-authored-by: Ilkka Seppälä <iluwatar@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
package com.iluwatar;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
/**
|
||||
* The `App` class demonstrates the functionality of the {@link Money} class, which encapsulates
|
||||
* monetary values and their associated currencies. It showcases operations like addition,
|
||||
* subtraction, multiplication, and currency conversion, while ensuring validation and immutability.
|
||||
*
|
||||
* <p>Through this example, the handling of invalid operations (e.g., mismatched currencies or
|
||||
* invalid inputs) is demonstrated using custom exceptions. Logging is used for transparency.
|
||||
*
|
||||
* <p>This highlights the practical application of object-oriented principles such as encapsulation
|
||||
* and validation in a financial context.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
// Initialize the logger
|
||||
private static final Logger logger = Logger.getLogger(App.class.getName());
|
||||
/**
|
||||
* Program entry point.
|
||||
*
|
||||
* @param args command line args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// Create instances of Money
|
||||
Money usdAmount1 = new Money(50.00, "USD");
|
||||
Money usdAmount2 = new Money(20.00, "USD");
|
||||
|
||||
// Demonstrate addition
|
||||
try {
|
||||
usdAmount1.addMoney(usdAmount2);
|
||||
logger.log(Level.INFO, "Sum in USD: {0}", usdAmount1.getAmount());
|
||||
} catch (CannotAddTwoCurrienciesException e) {
|
||||
logger.log(Level.SEVERE, "Error adding money: {0}", e.getMessage());
|
||||
}
|
||||
|
||||
// Demonstrate subtraction
|
||||
try {
|
||||
usdAmount1.subtractMoney(usdAmount2);
|
||||
logger.log(Level.INFO, "Difference in USD: {0}", usdAmount1.getAmount());
|
||||
} catch (CannotSubtractException e) {
|
||||
logger.log(Level.SEVERE, "Error subtracting money: {0}", e.getMessage());
|
||||
}
|
||||
|
||||
// Demonstrate multiplication
|
||||
try {
|
||||
usdAmount1.multiply(2);
|
||||
logger.log(Level.INFO, "Multiplied Amount in USD: {0}", usdAmount1.getAmount());
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.log(Level.SEVERE, "Error multiplying money: {0}", e.getMessage());
|
||||
}
|
||||
|
||||
// Demonstrate currency conversion
|
||||
try {
|
||||
double exchangeRateUsdToEur = 0.85; // Example exchange rate
|
||||
usdAmount1.exchangeCurrency("EUR", exchangeRateUsdToEur);
|
||||
logger.log(Level.INFO, "USD converted to EUR: {0} {1}", new Object[]{usdAmount1.getAmount(), usdAmount1.getCurrency()});
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.log(Level.SEVERE, "Error converting currency: {0}", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.iluwatar;
|
||||
/**
|
||||
* An exception for when the user tries to add two diffrent currencies.
|
||||
*/
|
||||
public class CannotAddTwoCurrienciesException extends Exception {
|
||||
/**
|
||||
* Constructs an exception with the specified message.
|
||||
*
|
||||
* @param message the message shown in the terminal (as a String).
|
||||
*/
|
||||
public CannotAddTwoCurrienciesException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.iluwatar;
|
||||
/**
|
||||
* An exception for when the user tries to subtract two diffrent currencies or subtract an amount he doesn't have.
|
||||
*/
|
||||
public class CannotSubtractException extends Exception {
|
||||
/**
|
||||
* Constructs an exception with the specified message.
|
||||
*
|
||||
* @param message the message shown in the terminal (as a String).
|
||||
*/
|
||||
public CannotSubtractException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.iluwatar;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Represents a monetary value with an associated currency.
|
||||
* Provides operations for basic arithmetic (addition, subtraction, multiplication),
|
||||
* as well as currency conversion while ensuring proper rounding.
|
||||
*/
|
||||
@Getter
|
||||
public class Money {
|
||||
private @Getter double amount;
|
||||
private @Getter String currency;
|
||||
|
||||
/**
|
||||
* Constructs a Money object with the specified amount and currency.
|
||||
*
|
||||
* @param amnt the amount of money (as a double).
|
||||
* @param curr the currency code (e.g., "USD", "EUR").
|
||||
*/
|
||||
public Money(double amnt, String curr) {
|
||||
this.amount = amnt;
|
||||
this.currency = curr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the given value to two decimal places.
|
||||
*
|
||||
* @param value the value to round.
|
||||
* @return the rounded value, up to two decimal places.
|
||||
*/
|
||||
private double roundToTwoDecimals(double value) {
|
||||
return Math.round(value * 100.0) / 100.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds another Money object to the current instance.
|
||||
*
|
||||
* @param moneyToBeAdded the Money object to add.
|
||||
* @throws CannotAddTwoCurrienciesException if the currencies do not match.
|
||||
*/
|
||||
public void addMoney(Money moneyToBeAdded) throws CannotAddTwoCurrienciesException {
|
||||
if (!moneyToBeAdded.getCurrency().equals(this.currency)) {
|
||||
throw new CannotAddTwoCurrienciesException("You are trying to add two different currencies");
|
||||
}
|
||||
this.amount = roundToTwoDecimals(this.amount + moneyToBeAdded.getAmount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts another Money object from the current instance.
|
||||
*
|
||||
* @param moneyToBeSubtracted the Money object to subtract.
|
||||
* @throws CannotSubtractException if the currencies do not match or if the amount to subtract is larger than the current amount.
|
||||
*/
|
||||
public void subtractMoney(Money moneyToBeSubtracted) throws CannotSubtractException {
|
||||
if (!moneyToBeSubtracted.getCurrency().equals(this.currency)) {
|
||||
throw new CannotSubtractException("You are trying to subtract two different currencies");
|
||||
} else if (moneyToBeSubtracted.getAmount() > this.amount) {
|
||||
throw new CannotSubtractException("The amount you are trying to subtract is larger than the amount you have");
|
||||
}
|
||||
this.amount = roundToTwoDecimals(this.amount - moneyToBeSubtracted.getAmount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies the current amount of money by a factor.
|
||||
*
|
||||
* @param factor the factor to multiply by.
|
||||
* @throws IllegalArgumentException if the factor is negative.
|
||||
*/
|
||||
public void multiply(int factor) {
|
||||
if (factor < 0) {
|
||||
throw new IllegalArgumentException("Factor must be non-negative");
|
||||
}
|
||||
this.amount = roundToTwoDecimals(this.amount * factor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the current amount of money to another currency using the provided exchange rate.
|
||||
*
|
||||
* @param currencyToChangeTo the new currency to convert to.
|
||||
* @param exchangeRate the exchange rate to convert from the current currency to the new currency.
|
||||
* @throws IllegalArgumentException if the exchange rate is negative.
|
||||
*/
|
||||
public void exchangeCurrency(String currencyToChangeTo, double exchangeRate) {
|
||||
if (exchangeRate < 0) {
|
||||
throw new IllegalArgumentException("Exchange rate must be non-negative");
|
||||
}
|
||||
this.amount = roundToTwoDecimals(this.amount * exchangeRate);
|
||||
this.currency = currencyToChangeTo;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user