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:
Ahmed-Taha-981
2025-01-06 19:19:22 +02:00
committed by GitHub
parent ac539606b1
commit cdb78d7fb6
8 changed files with 529 additions and 1 deletions
+65
View File
@@ -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;
}
}