mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-10-14 02:16:06 +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:
1 parent
ac539606b1
commit
cdb78d7fb6
8 files changed
+529
-1
No files matched your search
+168
@@ -0,0 +1,168 @@
|
||||
---
|
||||
title: "Money Pattern in Java: Encapsulating Monetary Values with Currency Consistency"
|
||||
shortTitle: Money
|
||||
description: "Learn how the Money design pattern in Java ensures currency safety, precision handling, and maintainable financial operations. Explore examples, applicability, and benefits of the pattern."
|
||||
category: Behavioral
|
||||
language: en
|
||||
tag:
|
||||
- Encapsulation
|
||||
- Precision handling
|
||||
- Currency safety
|
||||
- Value Object
|
||||
- Financial operations
|
||||
- Currency
|
||||
- Financial
|
||||
- Immutable
|
||||
- Value Object
|
||||
---
|
||||
|
||||
## Also known as
|
||||
|
||||
* Monetary Value Object
|
||||
|
||||
## Intent of Money Design Pattern
|
||||
|
||||
The Money design pattern provides a robust way to encapsulate monetary values and their associated currencies. It ensures precise calculations, currency consistency, and maintainability of financial logic in Java applications.
|
||||
|
||||
## Detailed Explanation of Money Pattern with Real-World Examples
|
||||
|
||||
### Real-world example
|
||||
|
||||
> Imagine an e-commerce platform where customers shop in their local currencies. The platform needs to calculate order totals, taxes, and discounts accurately while handling multiple currencies seamlessly.
|
||||
|
||||
In this example:
|
||||
- Each monetary value (like a product price or tax amount) is encapsulated in a `Money` object.
|
||||
- The `Money` class ensures that only values in the same currency are combined and supports safe currency conversion for global operations.
|
||||
|
||||
### In plain words
|
||||
|
||||
> The Money pattern encapsulates both an amount and its currency, ensuring financial operations are precise, consistent, and maintainable.
|
||||
|
||||
### Wikipedia says
|
||||
|
||||
> "The Money design pattern encapsulates a monetary value and its currency, allowing for safe arithmetic operations and conversions while preserving accuracy and consistency in financial calculations."
|
||||
|
||||
## Programmatic Example of Money Pattern in Java
|
||||
|
||||
### Money Class
|
||||
|
||||
```java
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
public Money(double amnt, String curr) {
|
||||
this.amount = amnt;
|
||||
this.currency = curr;
|
||||
}
|
||||
|
||||
private double roundToTwoDecimals(double value) {
|
||||
return Math.round(value * 100.0) / 100.0;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
public void multiply(int factor) {
|
||||
if (factor < 0) {
|
||||
throw new IllegalArgumentException("Factor must be non-negative");
|
||||
}
|
||||
this.amount = roundToTwoDecimals(this.amount * factor);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
## When to Use the Money Pattern
|
||||
|
||||
The Money pattern should be used in scenarios where:
|
||||
|
||||
1. **Currency-safe arithmetic operations**
|
||||
To ensure that arithmetic operations like addition, subtraction, and multiplication are performed only between amounts in the same currency, preventing inconsistencies or errors in calculations.
|
||||
|
||||
2. **Accurate rounding for financial calculations**
|
||||
Precise rounding to two decimal places is critical to maintain accuracy and consistency in financial systems.
|
||||
|
||||
3. **Consistent currency conversion**
|
||||
When handling international transactions or displaying monetary values in different currencies, the Money pattern facilitates easy and reliable conversion using exchange rates.
|
||||
|
||||
4. **Encapsulation of monetary logic**
|
||||
By encapsulating all monetary operations within a dedicated class, the Money pattern improves maintainability and reduces the likelihood of errors.
|
||||
|
||||
5. **Preventing errors in financial operations**
|
||||
Strict validation ensures that operations like subtraction or multiplication are only performed when conditions are met, safeguarding against misuse or logical errors.
|
||||
|
||||
6. **Handling diverse scenarios in financial systems**
|
||||
Useful in complex systems like e-commerce, banking, and payroll applications where precise and consistent monetary value handling is crucial.
|
||||
|
||||
---
|
||||
## Benefits and Trade-offs of Money Pattern
|
||||
|
||||
### Benefits
|
||||
1. **Precision and Accuracy**
|
||||
The Money pattern ensures precise handling of monetary values, reducing the risk of rounding errors.
|
||||
|
||||
2. **Encapsulation of Business Logic**
|
||||
By encapsulating monetary operations, the pattern enhances maintainability and reduces redundancy in financial systems.
|
||||
|
||||
3. **Currency Safety**
|
||||
It ensures operations are performed only between amounts of the same currency, avoiding logical errors.
|
||||
|
||||
4. **Improved Readability**
|
||||
By abstracting monetary logic into a dedicated class, the code becomes easier to read and maintain.
|
||||
|
||||
5. **Ease of Extension**
|
||||
Adding new operations, handling different currencies, or incorporating additional business rules is straightforward.
|
||||
|
||||
### Trade-offs
|
||||
1. **Increased Complexity**
|
||||
Introducing a dedicated `Money` class can add some overhead, especially for small or simple projects.
|
||||
|
||||
2. **Potential for Misuse**
|
||||
Without proper validation and handling, incorrect usage of the Money pattern may introduce subtle bugs.
|
||||
|
||||
3. **Performance Overhead**
|
||||
Precision and encapsulation might slightly affect performance in systems with extremely high transaction volumes.
|
||||
|
||||
---
|
||||
|
||||
## Related Design Patterns
|
||||
|
||||
1. **Value Object**
|
||||
Money is a classic example of the Value Object pattern, where objects are immutable and define equality based on their value.
|
||||
Link:https://martinfowler.com/bliki/ValueObject.html
|
||||
2. **Factory Method**
|
||||
Factories can be employed to handle creation logic, such as applying default exchange rates or rounding rules.
|
||||
Link:https://www.geeksforgeeks.org/factory-method-for-designing-pattern/
|
||||
---
|
||||
|
||||
## References and Credits
|
||||
|
||||
- [Patterns of Enterprise Application Architecture](https://martinfowler.com/eaaCatalog/money.html) by Martin Fowler
|
||||
- [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)
|
||||
Reference in new issue
Block a user