dennis-fedco Posted June 17, 2014 Share Posted June 17, 2014 I am working on a module that receives some info and provides dimensions and weights of products to the caller. The way I get those is from existing Excel tables used by the company. Some product types have their dimensions only. Some have both dimensions and weights. To clarify - all products have both weight and dimensions but not all are specified on the Excel tables that I am using. so say "Apple" has dimensions on 1 x 1 x 1, but no weight is given. (Weight can be computed separately and in fact there is an existing class that does this already for Pear.). and "Pear" has dimensions 2 x 1 x 1 and weighs 1lbs. In short, some classes have both getWeight() and getDimensions() methods, like Pear(), and some classes just have getDimensions(), like Apple(). I am confused as to which way to go. I can create PearDimensions() class and PearWeight() and separate concepts of "weight" and "dimensions" some more and use a DimensionFactory() and WeightFactory() to instantiate the right object for the circumstances, or I can use "implements" WeightAwaretInterface and HeightAwaretInterface on Apple/Pear classes and leave them as is, thus mixing up the Weight/Dimension getters/causes. So in short I am a tad confused and wondering if there is just a good way to maintain these. Right now I am using DimensionFactory() and WeightFactory() and instantiate Pear class twice (once in each factory) since Pear has both getWeight() and getDimensions() methods. I feel weird creating the same Pear object in both factories. Do you have a recommendation for this, or do I just "hack it" (i.e. leave it as is)? Quote Link to comment Share on other sites More sharing options...
Solution requinix Posted June 17, 2014 Solution Share Posted June 17, 2014 Since the weight and dimension are properties, not objects, this is technically more of a "strategy" than a "factory". Though you may very well use a factory to get the strategy, or go with a more dependency-injected route. Not knowing the entire application, I'd go with a base class that provides the weight and dimensions. When a value is available, it is used, and when the value is not available, it does stuff to calculate (and then update) the value. abstract class Fruit { private $weight; private $dimensions = array(); // [w, h, d] public function getWeight() { if (!$this->weight) { if ($this->dimensions) { $this->weight = FruitStrategy::factory($this)->getWeight($this->dimensions); } else { // not enough information } } return $this->weight; } } class Apple extends Fruit { } class Pear extends Fruit { } abstract class FruitStrategy { public static function factory(Fruit $fruit) { $class = get_class($fruit) . "Strategy"; return new $class(); } public abstract function getWeight($dimensions); } class AppleStrategy extends FruitStrategy { public function getWeight($dimensions) { return 0.5 * $dimensions[0] * $dimensions[1] * $dimensions[2]; } }Even further, getWeight will probably look about the same for everything. So why not provide a default implementation? abstract class FruitStrategy { public static function factory(Fruit $fruit) { $class = get_class($fruit) . "Strategy"; return new $class(); } public function getWeight($dimensions) { return $this->getWeightMultiplier() * $dimensions[0] * $dimensions[1] * $dimensions[2]; } protected abstract function getWeightMultiplier(); } class AppleStrategy extends FruitStrategy { protected function getWeightMultiplier() { return 0.5; } } Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.