Jump to content

Factories and Interfaces Turmoil


dennis-fedco

Recommended Posts

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)?

Link to comment
https://forums.phpfreaks.com/topic/289181-factories-and-interfaces-turmoil/
Share on other sites

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;
	}

}

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.