0

There is a base class Product having all the generic properties and methods which a product should have.

abstract class Product
{   
    public abstract function process();
}

Now, These are the few types of products which may or may not have similar logic.

class Shirt extends Product
{
    public function process()
    {
        return 0;
    }
}

class Trouser extends Product
{
    public function process()
    {
        return 1;
    }
}

class PocketSquare extends Product
{
    public function process()
    {
        return 2;
    }
}

I've used switch statement to distinguish and initialise objects.

$products = $db->query("SELECT * FROM products LIMIT 10");
foreach ($products as $key => $product) {
    switch ($product->type) {
        case 'shirt':
            $products[$key] = new Shirt($product);
            break;
        case 'trouser':
            $products[$key] = new Trouser($product);
            break;
        case 'pocketsquare':
            $products[$key] = new PocketSquare($product);
            break;
    }   
}

Is there any way to avoid switch statement? or any better approach?

kamal pal
  • 111
  • 3
  • Is there any reason you want to avoid the `switch`? – Vincent Savard Jul 16 '19 at 12:41
  • Yes, because this switch statement will be sitting in a class which breaks open/close principle, as later more product types can be added. – kamal pal Jul 16 '19 at 12:50
  • @kamalpal The Open/Closed principle is from the point of view of the _clients_ of your class. In this case, you've already abstracted `Product` away, and its clients will only depend on the interface, and not any concrete implementations. If you add new concrete implementations, you will not have to modify the clients, and therefore, **you respect the Open/Closed principle**. Your `switch` is essentially a Factory which instantiate the correct implementation. This is absolutely fine. – Vincent Savard Jul 16 '19 at 13:39
  • @VincentSavard ok, didn't realised that.Thanks for your views! – kamal pal Jul 16 '19 at 16:25

1 Answers1

0

The common alternative to this is take a declarative approach to the solution: replace that switch statement with a hashmap of lambdas.

I've not used PHP in years, so I've likely got the below syntax wrong, but you'd do something like:

$productsMap = array (
    'shirt' => function ($p) { return new Shirt($p); },
    'trouser' => function ($p) { return new Trouser($p); },
    'pocketsquare' => function ($p) { return new PocketSquare($p); }

);

...

$products = $db->query("SELECT * FROM products LIMIT 10");

foreach ($products as $key => $product) {
    $products[$key] = $productsMap[$product->type]();
}
David Arno
  • 38,972
  • 9
  • 88
  • 121