Как использовать принцип Open/Closed для замены блока переключателя, который изменяет общее состояние

Я работаю над проектом, который требует от меня создания отчета на основе купленной аренды. Я должен вести подсчет для каждого типа аренды и суммировать соответствующие итоги. В настоящее время я использую блок переключателей, чтобы определить, какое действие следует предпринять в зависимости от текущей арендной платы. Однако, насколько я понимаю, это нарушает принцип открытости/закрытости, поскольку мне придется изменять блок переключателей каждый раз, когда добавляется новая аренда. Я хотел бы, чтобы это встретилось с OCP, но я не уверен, как это сделать. Ниже мой код:

public function generateReport($rentals)
{
    $type_1_count = 0;
    $type_2_count = 0;
    $type_3_count = 0;

    $type_1_sum = 0;
    $type_2_sum = 0;
    $type_3_sum = 0;

    foreach ($rentals as $rental) {
        switch ($rental->type) {
            case 'TYPE_1':
                $type_1_count++;
                $type_1_sum += $rental->price;
                break;
            case 'TYPE_2':
                $type_2_count++;
                $type_2_sum += $rental->price;
                break;
            case 'TYPE_3':
                // some of the rentals include other rentals which must be accounted for
                $type_1_count++;
                $type_1_sum += $rental->price / 2;

                $type_3_count++;
                $type_3_sum += $rental->price / 2;
                break;
            default:
                echo 'Rental Not Identified';
        }
    }
    return compact('type_1_count', 'type_2_count', 'type_3_count', 'type_1_sum', 'type_2_sum', 'type_3_sum');
}

Я изменяю общие переменные состояния в зависимости от выбранного случая. Я просмотрел много примеров OCP, но все они показывают, как выполнить действие или вернуть значение, но вместо этого мне нужно изменить общее состояние. Как лучше всего реорганизовать этот код, чтобы он больше соответствовал OCP?


person user12206763    schedule 29.01.2020    source источник


Ответы (1)


Вы можете использовать ассоциативный массив. Вам просто нужно сначала убедиться, что переменная установлена. Что-то вроде этого:

   $all_rentals = [];
   foreach ($rentals as $rental) {
       // make sure the variable has a default value
       if(!isset($all_rentals[$rental->type."_count"]) {
           $all_rentals[$rental->type."_count"] = 0;
           $all_rentals[$rental->type."_sum"] = 0;
       }
       $all_rentals[$rental->type."_count"]++;
       $all_rentals[$rental->type."_sum"] += $rental->price;
   }

...

Таким образом, вы можете добавлять новые значения (типы аренды) без изменения существующего кода.

person Michael Peng    schedule 29.01.2020
comment
Спасибо за ваш ответ, он очень близок к тому, что я искал. Единственный оставшийся вопрос: что делать, если мне нужно выполнить разные действия в зависимости от типа аренды? Например, аренда Типа 3 обрабатывается немного иначе, чем другие, в том, как они подсчитываются и суммируются. Мне все еще нужен оператор switch или я могу каким-то образом использовать полиморфизм? - person user12206763; 29.01.2020
comment
Расчеты всегда разные? Если это так, то случай переключения, вероятно, лучше всего, если вы не хотите использовать несколько условий IF. - person Michael Peng; 29.01.2020