Jump to content

Factories and Interfaces Turmoil


Go to solution Solved by requinix,

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

  • Solution

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

}
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • 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.