Jump to content

How to struture class when products are different?


dennis-fedco
Go to solution Solved by ignace,

Recommended Posts

conceptually I have a class that holds data and operations on a product line of products.

I wrote the class originally for a Product Line with model numbers B, C, D, E.  All of these worked similarly so my class had methods for those model numbers.

 

Later:  a new product number A was added for this product line.  Turns out model A despite being from the same product line, has different features and somewhat different data, and somewhat different computation patters.

 

I am hacking up my class and now see things like

public someMethod()
{
    if ($this->modelNumber == 'A')
    {
        //do this special thing
    }
    else
    {
        //proceed as before for models B, C, D, E
    }

    //otherwise, do things that apply to all models, including A, B, C, D, E
}

Somehow I feel that eventually I will end up with a switch statement for multiple models and conventional wisdom says it is not the way to go.  That I am to use polymorphism instead.

 

Well, great, but how?    Do I perhaps just extend my product class like
 

class ProductA extends Product
{
    //my specific A model stuff here
}

If I do this though I will essentially move my If/then/else to the main code.  i.e.

if ($this->modelNumber == 'A') $product = new ProductA();  //A product
else $product = new Product();  //general B, C, D, E

and THAT will become the switch statement eventually.  So polymorphism does not solve anything for me here.

How do I then write / restructure my class, if at all ?

Edited by dennis-fedco
Link to comment
Share on other sites

Not by any means an OOP guy, but I have the basic understanding to say this.

 

When designing a class you look for the common denominators of the thing(s) that you are creating it for. If everything you know about your objects can produce a set of properties and methods that are the same for all, then those are things in your "starting" class. When you start to say to yourself - ok, I need to handle b,c,d differently that's when you start to identify a subset of properties and methods for those things and create a sub class that a) inherits the base functionality from the first class and b) adds some new functionality for the new oddballs. You don't begin to modify the methods of the main parent class to accommodate, but rather build a new object that is more flexible. That is polymorphism wherein you morph your object by adding new features to the child class which "extends" the overall functionality of the first class. (Extends - as in "Class mynewclass Extends OldClass"). The key is to recognize ALL the properties and actions that the set of things has in common so that you don't duplicate method/props in a second class.

 

I'm sure you will get many responses to this post now, with many telling me I'm way off base ( I don't think so) and others giving you a more detailed, technical oriented description, but IMHO I think I have given you some food for thought on how to proceed.

Edited by ginerjm
Link to comment
Share on other sites

I've seen your questions pass on these forums and they are always very vague and very abstract. So at best you get a very vague and very abstract answer for which the chances of it actually solving your design problems are less than likely. But anyway here goes:

 

How about:

 

public function someMethodFromSomeGhostClass {
  $this->model->doSomeMethodFromSomeClassInsideGhostClassAndCrossFingers();
}
Link to comment
Share on other sites

I will rephrase.  I have:

  • Mustang 2013
  • Mustang 2014

Both have wheel sizes of 17" x 8".  So I create a Mustang class and it loads wheel specs as part of constructor.  In fact I hardcoded it.

class Mustang
{
    function __construct()
    {
        $wheels = "17 x 8";
    }
}

Now I am adding

  • 2012 Mustang Boss 302

Wheel specs are 19" x 9"

 

My class can now look as such:

class Mustang
{
    function __construct($model)
    {
        switch($model)
        {
            case 'Mustang 2013': $wheels = "17 x 8";break;
            case 'Mustang 2014': $wheels = "17 x 8";break;
            case '2012 Mustang Boss 302': $wheels = "19 x 9";break;
            default:
        }
    }
}

I don't think it is good design and I want to change it.

 

Link to comment
Share on other sites

class Automobile implements iAutoDetails{
    private $_model;

    function __construct($model){
        $this->_model = new $model();
     }
}

interface iAutoDetails{
    public function getWheelBase();
}

class Mustang2013 extends Automobile{
    private $_wheels = '17 x 8';

    public function getWheelBase(){
        return $this->_wheels;
    }
}

class Mustang2012Boss302 extends Automobile{
    private $_wheels = '19 x 9';

    public function getWheelBase(){
        return $this->_wheels;
    }
}

$auto = new Automobile('Mustang2012Boss302');
print("<p>{$auto->getWheelBase()}</p>");
//prints 17 x 8
$auto2 = new Autmobile('Mustang2013');
print("<p>{$auto2->getWheelBase()}</p>");
//prints 19 x 9

I think the issue is your current object setup. Personally, I'd do the above - that way it really doesn't matter at all what automobile you're instantiating, you know you can call getWheelBase() and you'll get the proper wheel base measurements. Obviously, you'd put any and all common functionality in the parent class (Automobile) while saving the model-specific functionality and information for the child classes. The interface insures that you've got a consistent api when dealing with new objects.

Edited by maxxd
Link to comment
Share on other sites

  • Solution

maxxd has the right idea, but i would keep it simple like this:

 

abstract class Auto {
   abstract public function getWheelBase();
}

class Mustang2013 extends Auto {
   public function getWheelBase() {
     return new WheelBase(17, ;
   }
}
Other option is to pass specific info to the class:

 

class Auto {
  private $wheelBase;
  
  public function __construct(WheelBase $wheelBase, ..) {
    ..
  }
}
Link to comment
Share on other sites

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.