11

I'm basically creating a display-module for an ad-system I've created.

I'm trying to avoid the following construction, with repeated if-statements.

My gut feeling tells me there's a smarter way to do this, maybe with polymorphism?

<?php

class Ad { 
    public $adState = 'active'; 
} 

class AdWriter { 
    public function displayAd(Ad $ad, $viewmode = 'visitor') { 
        if ($viewmode =='visitor') { 
            if ($adState == 'active') {} 

            else if ($adState == 'paused') {} 

            else if ($adState == 'inactive') {} 

        } 

        else if ($viewmode = 'owner') { 
            if ($adState == 'active') {} 

            else if ($adState == 'paused') {} 

            else if ($adState == 'inactive') {} 
        } 

        else if ($viewmode == 'administrator') { 
            if ($adState == 'active') {} 

            else if ($adState == 'paused') {} 

            else if ($adState == 'inactive') {} 
        } 
    } 
}  

?>

6 Answers 6

16

Apply the Refactoring Replace Conditional with Polymorphism and have a look at the State Pattern.

Sign up to request clarification or add additional context in comments.

1 Comment

Does replacing conditional with polymorphism not just mean your putting your conditionals behind creating objects instead of calling methods etc
4

You could create an Factory (Pattern), using an switch on viewmode and create an specific Ad implementing an interface having an simple function 'display' for example.

Pseudo example:

class AdFactory { 

    public static function getAd($sType) {
        switch($sType) {
            case "AdOne":
                return new AdOne();
            case "AdTwo":
                return new AdTwo();
        }
    }
    throw new Exception("Unknown ad!");
}

class AdOne implement AdInterface {
    public function display() {
        // All that AdOne does when displaying.
    }
}

interface AdInterface {
    public function display() { }
}

$oAd1 = AdFactory::getAd('typeOne');
$oAd1->display();

$oAd2 = AdFactory::getAd('typeTwo');
$oAd2->display();

Comments

3

Instead of passing $viewmode, pass an object that would encapsulate the logic for this viewmore and call its method that would do the work. This way you'll avoid the need for if-statements.

Comments

0

I'm sneaking onto StackOverflow at work, so don't have time to write a detailed reply of all your possibilities.

But to 'tidy up' those ifs, you can do this:

switch $viewmode {
  case 'visitor':
    your_code_here;
    break;
  case 'owner':
    your_code_here;
    break;
  default:
    will_run_if_nothing_above_matches;
    break;
}

2 Comments

That didn't really eliminate anything though? I'm still stuck with repeatedly checking for the states.
Not if all states share an interface
0
  switch($viewmode){
    case "visitor":
        switch($adstate){
            case "active": 
                //statement
                break;
            case "paused": 
            break;
            case "inactive": 
            break;
        }
        break;
    case "owner":
        break;
    case "administrator":
        break;
}

Comments

0

In 8 chapter of this book you can find very detailed answer to your question.

In short: use Composition or Factories. (see answer of Wesley van Opdorp).

Also, avoid using string arguments as enumerable: $viewmode = 'visitor'
with this argument, you will have to keep in memory all possible values of this argument. Or look into code of function to remember them. And these values are strings - good place for typos. Also, it will be very difficult to change values in feature, because all calls of this method will contain hardcoded strings.
Use class-constants:

class AdWriter { 
const view_mode_visitor = 1;
...

Also, $adState - wrong code, should be $ad->state. But using public fields it's bad practice too :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.