Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 我如何解决这个OOP设计问题?_Php_Oop_Design Patterns - Fatal编程技术网

Php 我如何解决这个OOP设计问题?

Php 我如何解决这个OOP设计问题?,php,oop,design-patterns,Php,Oop,Design Patterns,我的系统有3个组件: 报表-包含用于定义报表在其输出中实际包含内容的逻辑。示例包括TopMerchantsReport和LowestTransactionsReport ReportRunner-由于报表只收集和生成数据,此类负责运行所有报表并发送结果(例如,通过电子邮件)。每个报告都有自己的ReportRunner ReportProfile-包含特定报表的用户设置的数据库表的对象镜像 报告可以具有多个可插拔行为,例如可消化的和/或可可调度的。由于PHP没有mixin,因此最好用decora

我的系统有3个组件:

报表-包含用于定义报表在其输出中实际包含内容的逻辑。示例包括
TopMerchantsReport
LowestTransactionsReport

ReportRunner-由于报表只收集和生成数据,此类负责运行所有报表并发送结果(例如,通过电子邮件)。每个
报告
都有自己的
ReportRunner

ReportProfile-包含特定报表的用户设置的数据库表的对象镜像


报告可以具有多个可插拔行为,例如可
消化的
和/或可
可调度的
。由于PHP没有mixin,因此最好用decorator模式来表示

我的实际问题是,当关联的
报告
用类似于
可调度
的东西修饰时,这3个对象中的每一个都需要修改其行为。例如,
ReportRunner
现在只需要收集计划的报告,
ReportProfile
将受益于
isScheduled()
方法


我不想强迫用户装饰所有3个类。这不仅容易出错,而且我还必须为每个行为创建3个装饰器(每个类一个)。还有什么其他的解决方案?

如果你想有一个具体的类,例如报告其他两个组件中的不同行为,你必须最终装饰它们,因此你无法避免。唯一的问题可能是管理这三个组件的创建,根据选择的行为进行装饰,例如可消化。这可以使用factory方法模式来完成,该模式允许您创建所有这三个组件的适当类型。

如果您想要有一个具体的类,例如报告其他两个组件中的不同行为,您必须最终装饰它们,因此您无法避免。唯一的问题可能是管理这三个组件的创建,根据选择的行为进行装饰,例如可消化。这可以使用工厂方法模式来完成,它允许您创建所有这三个组件的适当类型。

如果我正确理解您的痛苦,我唯一能想到的就是使用工厂设计。工厂有责任提供与特定报告相对应的ReportRunner和ReportProfile(基于其装饰)

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  
        }  
    }  
}
所以每个ReportRunner和ReportProfile都有一个类,非常相似

ReportRunner Factory应该有一个方法,该方法接受报表的装饰并返回其ReportRunner,因此您可以执行以下操作:

report->setReportRunner(  factoryReportRunner->getReportRunner(report->getDecorationType()  );
在FactoryReportRunner类中,您将有一个方法getReportRunner(…)


当然,对于每种装饰类型,您都必须有一个getDecorationReportRunner,在本例中:getDigestableReportRunnergetSchedulableReportRunner。ReportProfile的工厂也是如此。这样,每当添加新的装饰类型时,只需添加相应的getDecorationReportRunner和ReportProfile附带的装饰类型

如果我能正确理解你的痛苦,我唯一能想到的就是使用工厂设计。工厂有责任提供与特定报告相对应的ReportRunner和ReportProfile(基于其装饰)

所以每个ReportRunner和ReportProfile都有一个类,非常相似

ReportRunner Factory应该有一个方法,该方法接受报表的装饰并返回其ReportRunner,因此您可以执行以下操作:

report->setReportRunner(  factoryReportRunner->getReportRunner(report->getDecorationType()  );
在FactoryReportRunner类中,您将有一个方法getReportRunner(…)

当然,对于每种装饰类型,您都必须有一个getDecorationReportRunner,在本例中:getDigestableReportRunnergetSchedulableReportRunner。ReportProfile的工厂也是如此。这样,每当添加新的装饰类型时,只需添加相应的getDecorationReportRunner和ReportProfile附带的装饰类型