Object Hierarchy

Go To StackoverFlow.com

1

What is the correct model for a retail store? e.g. Company sells Products from Stores.

A company can have many stores and sell many products. The products aren't necessarily tied to each store, or so I would've thought.

I have a basic assignment, which asks that I design a system that calculates the economic order quantity of a product. We are supposed to implement a structure that will be suitable for a later assignment (for which we have no details..), and the advised structure is as follows:

public class Company {
    private Store store;

    public static void main(String[] args)
    {
        Store storeOne = new Store();

        storeOne.setEOQRelevantValues(1, etc..);
    }
}

public class Store {
    private Product product;

    //..

    public setEOQRelevantValues(int eoqRelevantValues)
    {
        Product.setEOQRelevantValues(eoqRelevantValues);
    }
}

public class Product{
    private int eoqRelevantValues;

    //..

    public setEOQRelevantValues(int eoqRelevantValues)
    {
        this.eoqRelevantValues = eoqRelevantValues;
    }

    public int calculateEOQ()
    {
        //do stuff with this.eoqRelevantValues..
        return EOQ;
    }
}

This seems to violate all of the little I know about OOP. Methods that pass data down through the hierarchy - duplicating parameters between objects? What am I missing?

2012-04-04 07:34
by underskor
That looks to be a botched Composition setup, and definitely not a correct useful object-graph setup. I don't get why "Product is [supposed to be] a Store" or "Store is [supposed to be] a Product", for instance. Is that really what was shown/suggested - NoName 2012-04-04 07:44
@pst - yeah, the next assignment will require multiple stores and products under those stores - underskor 2012-04-04 11:08


2

You're correct to be concerned in that it would be unusual to initialise a hierarchy of objects by passing in all the parameters from the top down.

Your lecturer may be hinting that you implement something along the lines of the Composite pattern, whereby each class in the hierarchy shares a common method (e.g. getValue()). In the case of a Product (i.e. leaf node) this would simply return the product's value, whereas in the case of a Store or Company it would iterate over the constituent Products (or Stores), calling getValue() and summing the result.

The key difference between this and what you've written above is that you would typically initialise each Product individually via its constructor, rather than by passing in the data from another object. If the product is immutable you might choose to mark its fields as final. You might then choose to add utility methods to other classes in the hierarchy (e.g. moveProduct(Store store1, Store store1)); In other words the other classes would then exhibit behaviour rather than just being "data containers".

Example

/**
 * Optional interface for uniting anything that can be valued.
 */
public interface Valuable {
  double getValue();
}

/**
 * Company definition.  A company's value is assessed by summing
 * the value of each of its constituent Stores.
 */
public class Company implements Valuable {
  private final Set<Store> stores = new HashSet<Store>();

  public void addStore(Store store) {
    this.stores.add(store);
  }

  public void removeStore(Store store) {
    this.stores.remove(store);
  }

  public double getValue() {
    double ret = 0.0;

    for (Store store : stores) {
      ret += store.getValue();
    }

    return ret;
  }
}

/**
 * Store definition.  A store's value is the sum of the Products contained within it.
 */
public class Store implements Valuable {
  private final List<Product> products = new LinkedList<Product>();

  public void addProduct(Product product) {
    this.products.add(product);
  }

  public void removeProduct(Product product) {
    this.products.remove(product);
  }

  public double getValue() {
    double ret = 0.0;

    for (Product product : products) {
      ret += product.getValue();
    }

    return ret;
  }
}

/**
 * Product definition.  A product has a fixed inherent value.  However, you could
 * always model a product to depreciate in value over time based on a shelf-life, etc.
 * In this case you might wish to change the Valuable interface to accept a parameter;
 * e.g. depreciationStrategy.
 */
public class Product implements Valuable {
  private final double value;

  public Product(double value) {
    this.value = value;
  }

  public double getValue() {
    return value;
  }
}
2012-04-04 07:41
by Adamski
Thank you for your response. I had a read over the Composite pattern but it seems a little above me at this stage and I'm struggling to grasp what you mean. Is there any chance you could provide a brief code sample? :) Thank - underskor 2012-04-04 11:10
@Thomas: Example added - Adamski 2012-04-04 11:48
Ads