Как я могу решить эту проблему проектирования ООП? - PullRequest
2 голосов
/ 17 января 2011

У меня есть система, которая состоит из 3 компонентов:

Отчет - Содержит логику для определения того, что отчет действительно содержит в своих выходных данных. Примеры включают TopMerchantsReport и LowestTransactionsReport.

ReportRunner - Так как отчеты выполняют только сбор и генерацию данных, этот класс отвечает за запуск всех отчетов и отправку результатов (например, по электронной почте). Каждый Report имеет свой собственный ReportRunner.

ReportProfile - Зеркало объекта таблицы базы данных, которая содержит настройки пользователя для определенного отчета.


A Report может иметь несколько подключаемых режимов, например, Digestable и / или Schedulable. Поскольку в PHP нет миксинов, это лучше всего представить шаблоном декоратора.

Моя настоящая проблема заключается в том, что каждый из этих 3 объектов нуждается в изменении своего поведения, когда связанный Report украшен чем-то вроде Schedulable. Например, ReportRunner теперь нужно собирать только запланированные отчеты, а ReportProfile выиграет от метода isScheduled().

Я не хочу заставлять пользователя украшать все 3 класса. Эта ошибка не только подвержена ошибкам, но и мне придется создавать 3 декоратора для каждого поведения (по одному для каждого класса). Какое еще решение есть?

Ответы [ 3 ]

0 голосов
/ 23 января 2011

Если вы хотите иметь для конкретного класса, например, Сообщайте о различном поведении в двух других компонентах, вы должны в конечном итоге украсить их, поэтому вы не можете избежать этого. Единственной проблемой является управление созданием этих трех компонентов, которые должны быть оформлены в соответствии с выбранным поведением, например, Перевариваемого. Это можно сделать с помощью шаблона фабричного метода, который позволяет вам создать соответствующий вид всех этих трех компонентов.

0 голосов
/ 22 ноября 2013

Единственное, о чем я могу подумать, если я правильно понимаю ваше испытание, это использовать Factory Design.Фабрика будет нести ответственность за предоставление ReportRunner и ReportProfile, которые соответствуют конкретному отчету на основе его оформления.

Таким образом, у вас будет класс для каждого ReportRunner и один класс для ReportProfile, очень похожий.

ReportRunner Factory должен иметь метод, который принимает оформление отчета и возвращает его ReportRunner, поэтому вы должны сделать что-то вроде:

report->setReportRunner(  factoryReportRunner->getReportRunner(report->getDecorationType()  );

В классе FactoryReportRunner выу нас был бы метод getReportRunner (...)

getReportRunner(decorationType){
     $functionToCall = $this->'get'.decorationType.'ReportRunner';
     if(function_exists($functionToCall) && 
                      is_callable(array($this, $functionToCall))){
         return $this->$functionToCall();
     }else{
         //log or alert as error
     }
}

Конечно, тогда вам нужно было бы иметь getDecorationReportRunner для каждого типа украшения,в этом случае: getDigestableReportRunner и getSchedulableReportRunner .То же самое относится и к фабрике для ReportProfile.Таким образом, каждый раз, когда вы добавляете новый тип оформления, все, что вам нужно, это добавить соответствующий getDecorationReportRunner и тот, который также идет с ReportProfile.

0 голосов
/ 17 января 2011
class Report{
    const SCHEDULED = 1;  
    const DIGESTABLE = 2;  

    private $behaviour;  

    public function getReportData(){}  
    public function getReportProfile(){}  
    public function getBehaviour(){
        return $this->behaviour;
    }
}  

class ReportRunner{  
    public function runReport(){  
        switch($this->report->getBehaviour()){  
            case Report::SCHEDULED
            //do sheduled stuff  
            case Report::DIGESTABLE
            //do DIGESTABLE stuff  
        }  
    }  
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...