1

I was wondering if we could apply design patterns to writing code for currency conversion, and if yes then what would they be? The assumption is that conversion rates are static and we can hard-code them.

I thought about using 'state pattern' where every state represents a specific currency and has formulas encapsulated into corresponding methods for conversion, e.g. 'toDollars()', 'toPounds()' etc.

Another possibility (not sure if it's a design pattern) is using function objects that convert from a specific currency to another, and storing them as values in a 2-level Hashtable where the first level key is 'from' currency and the second level key is 'to' currency.

Are there any other design patterns to apply to this problem? The problem at its most abstract level is that we have 'm' entities and they are all inter-convertible based on some specific rules. Examples are converting time zone values in to each other; calendar dates from different calendar types (Gregorian/Chinese) etc. into each other.

Thanks and regards!

skaffman
  • 398,947
  • 96
  • 818
  • 769
shrini1000
  • 7,038
  • 12
  • 59
  • 99

3 Answers3

3

From a learning/design point of view this question is totally backward since the aim should not be to apply design patterns, but to solve problems and to communicate about the solutions and design patterns help with that.

But since you asked: Tons of design patterns might make sense depending on the requirements:

  • Chain of Responsibility: Have a list of Converters which you consult one after the other, until one can convert the currencies at hand
  • Factory Method: Create a Converter based on the original and target currency
  • Facade/Decorator: Create an amount in one currency from another currency and a Converter, hiding the api from the client.
  • Singleton: In case you want to make sure you have only one Converter for each Conversion
  • Value Object ...

I recommend this video: http://www.infoq.com/presentations/Value-Objects-Dan-Bergh-Johnsson It is overkill for the question but it happens to use currency conversion as an example for Value Objects ...

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
3

Converting is simple arithmetic, why would you need fancy code constructs? You've essentially a table of conversion rates matched with currency codes (or grid if you want to convert from any to any rather than from one to any and back). Select the correct rate from the table or grid, and perform a simple division or multiplication (depending on the direction of the conversion).

No design patterns required, unless maybe you want to get real fancy and create a class for each specific conversion (from-to pair) in which case you might look at a factory to create instances of those classes depending on the currency codes you hand the factory. Put a decorator or facade over the factory so all you have to do is call a single method which then calls the factory and uses the result. And who knows, you might want to make that facade a singleton so you won't have to create multiple instances.

But all that would be overkill for this problem, though they might maybe be appropriate in a system that performs the conversion as part of its functionality and wants to expose different calculations through a common interface (like a plugin architecture).

jwenting
  • 5,505
  • 2
  • 25
  • 30
2

Basically, currency conversion is a graph problem, with nodes corresponding to different currencies and edges corresponding to conversions between different currencies. Finding the shortest conversion path is easy to do by using for example breadth-first-search, and after you find a connection between two currencies, you can create a new direct edge between them. To make the graph fast to process, you could store each node separately and store a node's connections in a map from currency names to edges. Edges would store the conversion rate and pointers to target / source currency nodes. Alternatively, you could use the matrix representation of a graph. It's easy to apply this to both symmetric and asymmetric conversion, using a directed or non-directed graph. However, asymmetric rates are probably better to implement with a separate calculation after finding the connection than with storing them in a graph, unless you have a complete conversion table between all the currencies to start with.

No need to get fancier than that, especially if you have static conversion rates. Hard-coding everything with functions like toPounds() doesn't seem sensible, unless you have very few currencies. An API like convert(int amountInFixedPoint, string fromCurrency, string toCurrency) is much more flexible.

Olli Etuaho
  • 303
  • 4
  • 9