试图重用代码,但不能扩展两个类,替代?

时间:2016-07-18 07:55:29

标签: php extend

我知道我不能从两个班级延伸,但对我的案例有什么选择?

我正在使用基类parser来解析我的CMS页面。此类包含过滤从数据库检索的数据并将其呈现为HTML页面所需的所有基本功能。

所有其他类都需要解析器,因为如果没有它,它们就无法工作。

我有两种模式:

  1. CMS内部
  2. CMS之外
  3. 内部CMS

    如果在CMS内部,则会将userdata和其他附加数据加载到类中。

    CMS之外

    如果在CMS之外,只加载了呈现页面所需的数据,这是向访问该网站的人显示页面的默认方式。

    模块

    页面可用于显示默认数据/元素,但它也可用于显示来自模块(例如日历页面)的数据。 如果是这种情况,需要将其他数据加载到解析器对象中,因此我有4种不同的用例:

    1. 解析器模式
    2. cmsParser模式(在CMS内)
    3. moduleParser模式(加载了模块数据的解析器)
    4. cmsModuleParser模式(两者)
    5. 我有以下[极简化]课程:

      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,因为我仍然需要添加重复变量等。

      我当然不想要重复的代码,那么如何解决这个难题?

2 个答案:

答案 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。这当然是错误的,会导致像你这样的问题。有许多例子,其中继承是有用的,如

  • 女人是人
  • 丰田是一辆汽车
  • PageController是一个控制器(MVC更常见的场景 应用)

但继承如

  • 汽车是引擎
  • 女人是一条腿
  • cmsModuleParser是Parser

不是一个好的设计,问题很明显。

那么你如何解决问题?  让我们坚持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注入这种方式,你的依赖关系之间的耦合松散,你有一个更好的设计。

在谷歌搜索依赖注入组合而不是继承概念。