Gary Cohan said:
Lets say you have two classes,
Product
and
Category.
In my e-commerce application, each category can have multiple products, and
each product and be on multiple categories.
So obviously, each Product has a collection of Category objects, and each
Category has a collection of Product objects.
My question is, if you wanted to add a product to a category and thus have a
new category <--> product mapping, would you expect to add the product to
the category, and then add the category to the product as two seperate
method calls, or is there some commonly used collection idiom that takes
care of this ?
As an alternative to the other suggestions, you might also consider
have both Product and Category contain a shared bidirectional map of
products<->categories. This map would be created and stored in advance
in Product and Category objects. This localizes the bidirectional
mapping to one class.
Example, written to run in one file:
import java.util.*;
public class TestBiMap {
public static void main(String args[]) {
BiMap categories = new BiMap();
Product wrench = new Product("wrench", categories);
Product book = new Product("book", categories);
Category tool = new Category("tool", categories);
Category discounted = new Category("discounted", categories);
wrench.addCategory(tool);
wrench.addCategory(discounted);
book.addCategory(discounted);
System.out.println("Wrench categories: " +
wrench.getCategories());
System.out.println("Discounted products: " +
discounted.getProducts());
}
}
class BiMap {
Map values = new HashMap();
Map keys = new HashMap();
void add(Object key, Object value) {
collect(key, value, values);
collect(value, key, keys);
}
Collection getValues(Object key) {
return (Collection) values.get(key);
}
Collection getKeys(Object value) {
return (Collection) keys.get(value);
}
private void collect(Object key, Object value, Map map) {
Collection collection = (Collection) map.get(key);
if (collection == null) {
collection = new ArrayList();
map.put(key, collection);
}
collection.add(value);
}
}
class Product {
String myName;
BiMap myMap;
public Product(String name, BiMap map) {
myName = name;
myMap = map;
}
public void addCategory(Category category) {
myMap.add(this, category);
}
public Collection getCategories() {
return myMap.getValues(this);
}
public String toString() {
return myName;
}
}
class Category {
String myName;
BiMap myMap;
public Category(String name, BiMap map) {
myName = name;
myMap = map;
}
public void addProduct(Product product) {
myMap.add(product, this);
}
public Collection getProducts() {
return myMap.getKeys(this);
}
public String toString() {
return myName;
}
}