【问题标题】:OOP design question - Avoid repeating code in similar classes?OOP 设计问题 - 避免在类似的类中重复代码?
【发布时间】:2010-12-11 06:31:03
【问题描述】:

我正在为我们正在开发的网站的服务器端部分编写一堆 PHP 类。这些类看起来像这样:

class SomeEntity {
    // These fields are often different in different classes
    private $field1 = 0, $field2 = 0, ... ;

    // All of the classes have one of these
    static function create($field1, $field2) {
        // Do database stuff in here...
    }

    // All of the classes have similar constructors too
    function __construct($id_number) {
        // Do more database stuff in here...
    }

    // Various functions specific to this class
    // Some functions in common with other classes
}

问题是这些类有很多,它们都需要有类似的构造函数和一些通用函数,所以我最好写一个超类来处理所有这些东西,这样复制/粘贴的次数就会最少上。但是,每个子类都有不同的实例变量和参数,那么设计超类的最佳方式是什么?

(用更好的说法来表达,如何编写构造函数或其他函数来处理类的实例变量,但不一定知道类的实例变量是什么并按名称对它们进行硬编码?)

【问题讨论】:

  • 类之间有什么相似之处?也许您应该将它们抽象为它们自己的一个(或多个)类?让单一职责原则指导您。
  • 没有更清楚的理解你的问题,我只能告诉你把所有常用的共享函数放到一个父类中,并扩展它。 从不在项目中复制粘贴代码。
  • 是的,这就是我想要做的。我正在编写一个试图抽象出相似之处的超类,但这有点奇怪。例如,create 函数执行查询以检查对象是否已存在于数据库中,但它执行的查询取决于类(一些类具有唯一名称,其他类具有一些不同的唯一字段等)。我不确定如何概括这一点。

标签: php oop design-patterns


【解决方案1】:

你可以朝着一个非常通用的“实体”类型类走很多路,尤其是你利用了各种魔法方法。

考虑这样的类(只是一些随机的方便方法供类实体类共享):

<?php
abstract class AbstractEntity {

  protected $properties;

  public function setData($data){
    foreach($this->properties as $p){
        if (isset($data[$p])) $this->$p = $data[$p];
    }
  }

  public function toArray(){
    $array = array();
    foreach($this->properties as $p){
       $array[$p] = $this->$p;
       //some types of properties might get special handling
       if ($p instanceof DateTime){
           $array[$p] = $this->$p->format('Y-m-d H:i:s');
       }
    }
  }

  public function __set($pname,$pvalue){
     if (! in_array($pname,$this->properties)){
        throw new Exception("'$pname' is not a valid property!");
     }
     $this->$pname = $pvalue;
  }
}


<?php

class Person extends AbstractEntity {
   protected $properties = array('firstname','lastname','email','created','modified');
}

【讨论】:

  • 啊,这似乎是最优雅的解决方案。谢谢!
【解决方案2】:

基本上,您将重复的任何内容分成父类或辅助类。

如果它是与对象相关的常见活动,并且适用于类似的对象,则将其放在父类中并从其继承。如果此父级的子级具有相似的成员/属性,但无论出于何种原因命名不同,您只需编写接受参数的方法,然后在调用该方法时传递不同的属性名称。

如果它是与对象相关的公共活动,并且只有该对象,它就会成为需要它的子类中的方法。

如果它是与所讨论的类无关的常见活动,那么您创建一个新类来管理与该活动相关的事物,并在该类中编写一个公共方法,您的其他类可以调用。

【讨论】:

    猜你喜欢
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多