我知道我不能从两个班级延伸,但对我的案例有什么选择?
我正在使用基类parser
来解析我的CMS页面。此类包含过滤从数据库检索的数据并将其呈现为HTML页面所需的所有基本功能。
所有其他类都需要解析器,因为如果没有它,它们就无法工作。
我有两种模式:
内部CMS
如果在CMS内部,则会将userdata和其他附加数据加载到类中。
CMS之外
如果在CMS之外,只加载了呈现页面所需的数据,这是向访问该网站的人显示页面的默认方式。
模块
页面可用于显示默认数据/元素,但它也可用于显示来自模块(例如日历页面)的数据。 如果是这种情况,需要将其他数据加载到解析器对象中,因此我有4种不同的用例:
我有以下[极简化]课程:
class parser {
protected $oDataSource1;
protected $oDataSource2;
protected $oDataSource3;
//...
public function filterData() {
//.. Search through the data sources and return filtered data
}
}
class cmsParser extends parser {
protected $sUser_name;
protected $iUser_id;
protected $sUserLanguage;
///.. some functions here that are called only within the CMS
}
class moduleParser extends parser {
protected $mModuleData;
//.. Do something with this moduleData;
}
class cmsModuleParser extends ?? {
//... Get functions from the cmsParser + module functions
}
我能想出的唯一解决方案是使用moduleParser和cmsModuleParser都使用的特性? 这不是最佳IMO,因为我仍然需要添加重复变量等。
我当然不想要重复的代码,那么如何解决这个难题?
答案 0 :(得分:1)
您是否听说过赞成作品而不是继承这句话?有时,Composition会支付超过继承费用。在这种情况下,cmsModuleParser extends cmsParser
然后通过构造函数将moduleParser
作为依赖项注入。但是,getter
属性也有setter
和$moduleParser
。因此,如果您不需要通过构造函数注入它,您仍然可以从构造函数中删除它并使用setModuleParser()
访问器方法。 或者,您也可以编程到界面。下面的代码将说明这两个概念:
<强>组合物强>
<?php
class parser {
protected $mData;
//...
public function filterData() {
//.. filter the data here and return it
}
}
class cmsParser extends parser {
protected $sUser_name;
protected $iUser_id;
protected $sUserLanguage;
///.. some functions here that are called only within the CMS
}
class moduleParser extends parser {
protected $mModuleData;
//.. Do something with this moduleData;
}
// HERE YOU EXTEND THE cmsParser
// AND THEN USING DI, INCLUDE THE moduleParser
class cmsModuleParser extends cmsParser {
/**
* @var ModuleParser
*/
protected $moduleParser;
//... Get functions from the cmsParser + module functions
public function __construct(moduleParser $moduleParser) {
}
/**
* @return moduleParser
*/
public function getModuleParser() {
return $this->moduleParser;
}
/**
* @param moduleParser $moduleParser
* @return cmsModuleParser
*/
public function setModuleParser($moduleParser) {
$this->moduleParser = $moduleParser;
return $this;
}
}
编程接口
<?php
interface iParser{
public function filterData();
public function renderView();
public function saveData();
}
class parser implements iParser{
protected $mData;
//...
public function filterData() {
//.. filter the data here and return it
}
public function renderView(){}
public function saveData(){}
}
class cmsParser extends parser {
protected $sUser_name;
protected $iUser_id;
protected $sUserLanguage;
///.. some functions here that are called only within the CMS
}
class moduleParser extends parser {
protected $mModuleData;
//.. Do something with this moduleData;
}
class cmsModuleParser implements iParser {
//... Get functions from the cmsParser + module functions
public function __construct() {
}
public function filterData(){}
public function renderView(){}
public function saveData(){}
}
答案 1 :(得分:0)
首先,你必须知道所有类都扩展了一个被认为是糟糕设计的类,并表明你对OO概念的理解不够。
继承就像A is a B
一样。也就是说,你的所有类都是一个cmsParser。这当然是错误的,会导致像你这样的问题。有许多例子,其中继承是有用的,如
但继承如
不是一个好的设计,问题很明显。
那么你如何解决问题?
让我们坚持Car
案例。首先定义Car类
class Car extends Engine{
public function reverse(){
$this->startEngine();//Parent's method.
.....
}
而不是上面你可以做这样的事情
class Car{
protected $Engine;
protected $Driver;
public function __construct($Engine, $Driver){
$this->Engine = $Engine;
$this->Driver = $Driver;
}
public function reverse(){
$this->Engine->start();
$this->Driver->LookBehindYou();
...
}
}
使用contstructor注入这种方式,你的依赖关系之间的耦合松散,你有一个更好的设计。
在谷歌搜索依赖注入和组合而不是继承概念。