Not sure whether I picked the proper title. But anyway.
I've got to support and to develop already existing project.
It's built on OOP.
I've got such models as Order, Product. They are used very often into code.
Every model is bound to a corresponding table.
Client wants to integrate a new kind of customers into system. This kind of customers has different data associated with them and order completely different kinds of Products. So Order will look different.
What I decided is to not to mix the old kind of Order and the newly kind of it. At first I put them into separated tables in order not to break the working system and created different classes for them.
Now I have model Order.php and OrderNew.php, Product.php and ProductNew.php and so on.
I've global settings object where property of it holds what type of class I need to instantiate.
Now I've messed a lot of code with:
if ($global->object->isNewKindOfCustomer()) { $product = new ProductNew; } else { $product = new Product; } But doing so in many places I got strong feeling that I do something very VERY wrong.
So my first idea was that it should be decided by class Product what kidn of product should be instantiated.
It would be perfect if I could go to the old Product class and do in its constructor and do somethign like:
Class Product { __construct() { if ($global->object->isNewKindOfCustomer()) { $product = new ProductNew; } else { $product = new Product(); } } } Additionally I would inherit ProductNew from Product and redefine all methods that needs to be changed. Something like:
Class ProductNew extends Product { public methodsDefinedInProductButInNeedToBeChangedForProductNew (){ } } But the problem is that I didn't manage to find a sane way to do it in PHP and it still smells not so good. But much better than the first approach (at least for me).
The third idea is that I will create now just ProductNew class but also ProductOld class (what doesn't exist but what I got per se).
I will move all code from current Product class to ProductOld. So my current Product class will have no methods. It will get empty. Additionally ProductNew will inherit from ProductOld.
Having such scheme I won't touch code of whole system at all. Everywhere in the code the assignemnts will have the following look as
$product = new Product and inside I will need somehow to manager what object will be created in Product constructor.
The fourth idea is that I will create a generic class at first and name it as e.g. ProductGeneral . It will have mehtods related to both ProductNew and ProductOld classes. They both will extend ProductGeneral. And inside Product only the proper class will be instantiated depending on the role of current user. Although I'm not sure whether ProductGeneral is so necessary....
Still no idea how I can replace this in Product class. I remember it was called something like dynamic binding in C++.
Are there any better solutions for tackling this problem? Am I missing something?
Sorry for too long text I did try to make it as short as possible.
OrderandProduct.Productclass at all; instead, you could wrap the creation of those new classes into a separate factory.