简体   繁体   English

避免使用面向对象设计的if语句,PHP

[英]Avoiding if-statements with object oriented design, PHP

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. 我试图避免以下构造,重复if语句。

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') {} 
        } 
    } 
}  

?>

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. 您可以使用viewmode上的开关创建Factory(Pattern) ,并创建一个特定的Ad实现一个具有简单功能'display'的界面

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();

Instead of passing $viewmode, pass an object that would encapsulate the logic for this viewmore and call its method that would do the work. 而不是传递$ viewmode,传递一个对象,该对象将封装此视图的逻辑,并调用其方法来完成工作。 This way you'll avoid the need for if-statements. 这样您就可以避免使用if语句。

I'm sneaking onto StackOverflow at work, so don't have time to write a detailed reply of all your possibilities. 我正在工作中偷偷摸摸StackOverflow,所以没有时间写下你所有可能性的详细回复。

But to 'tidy up' those ifs, you can do this: 但要“整理”那些ifs,你可以这样做:

switch $viewmode {
  case 'visitor':
    your_code_here;
    break;
  case 'owner':
    your_code_here;
    break;
  default:
    will_run_if_nothing_above_matches;
    break;
}
  switch($viewmode){
    case "visitor":
        switch($adstate){
            case "active": 
                //statement
                break;
            case "paused": 
            break;
            case "inactive": 
            break;
        }
        break;
    case "owner":
        break;
    case "administrator":
        break;
}

In 8 chapter of this book you can find very detailed answer to your question. 本书的第8章中,您可以找到对您问题的非常详细的答案。

In short: use Composition or Factories. 简而言之:使用Composition或Factories。 (see answer of Wesley van Opdorp). (见Wesley van Opdorp的回答)。

Also, avoid using string arguments as enumerable: $viewmode = 'visitor' 另外,避免使用字符串参数作为枚举: $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. 另外, $adState - 错误的代码,应该是$ ad-> state。 But using public fields it's bad practice too :) 但是使用公共领域也是不好的做法:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM