如何在PHP中限制类实例?

时间:2016-04-15 16:13:32

标签: php class design-patterns registry

我对PHP(以及一般的编程)相对较新。记住这一点。

这是基本情景。我正在建立一个基于网络的迷你大学。

有两个关键类:课程 LessonSeries

  • 课程有一个Series属性,如果该课程属于一个系列,则会存储一个单独的LessonSeries 。它可能没有。
  • LessonSeries 有一个Lessons属性,它将包含一些Lesson对象..

这两个班级都有一个' Id' property,这是一个整数,对于它们的类是唯一的。我的数据库确保不会有两个Lessons或两个具有相同Id的LessonSeries。

在我的网站的许多页面中,Lesson对象被迭代并且(如果它们有一个系列),它们将显示它们所属的系列,并且有时使用一些其他LessonSeries方法和属性。

这就是问题所在:当从Db中提取课程时,它会构造一个LessonSeries来对应它。但我不希望在那里存在20个相同LessonSeries的实例。某些方法触发每个LessonSeries只需要执行一次的db查询。如果有20个基本相同的系列实例,这可能会导致数据库活动超过必要的指数。

我是编程模式的新手,但这是我想的我需要的东西:

  • 我想要一个独特的LessonSeries注册表。
  • 我希望所有课程都能分享每个独特的LessonSeries 属于它。
  • 理想情况下,我希望此功能在LessonSeries类中,而不必拥有第二个管理器类,如果它可能的话。
  • 基本上,我想要的是,每当构建LessonSeries时,将首先检查注册表是否存在id。如果是这样,返回的是对现有LessonSeries的引用。如果注册表中存在DOESN,则会照常创建。

有了这个说法,我不知道如何在PHP中实现这一点。

编辑: 评论中指出,我需要证明我已经尝试解决问题,因为这是一个很好的问题,在SO上。但那确实是我的问题。

我考虑做过这样的事情:

class LessonSeries {

private static $registry;

public $Id;
public $SeriesName;
public $ImagePath;
public $Description;
private $index;
private $lessons;
private $lessonCount;

public function __construct($seriesName, $imagePath=null, $Id=null, $description = null) {
    if(isset(self::$registry[$id])){
        return self::$registry[$Id];
    }else{
        $this->SeriesName = $seriesName;
        $this->ImagePath = $imagePath;
        $this->Id = $Id;
        $this->Description = $description;
        self::$registry[$Id] = $this;
    }    
}

但是,我不认为这是php构造函数的工作方式。我想我知道如何在Python中做我想做的事情(使用子类等),但PHP没有子类。那就是我在挣扎的地方。

1 个答案:

答案 0 :(得分:1)

这是你能做的。

  1. 创建工厂对象。将所有创建/缓存逻辑移到那里。
  2. 将该工厂传递给新创建的课程和系列,以便他们可以将创作委托给它。
  3. 在您的网页代码中,通过创建工厂进行策划。
  4. 尽可能避免使用静力学。例如,如果代码是真实对象,则代码将更容易进行单元测试。
  5. 这是一个展示它的伪代码:

    class LessonsFactory {
      private $lessons = [];
      private $series = [];
    
      public getLesson($id) {
        if (isset($this->lessons[$id])) {
            return $this->lessons[$id];
        }
        $lesson = $this->loadLesson($id);
        $this->lessons[$id] = $lesson;
        $this->getSeries($lesson[$id]);
      }
    
      private loadLesson($id) {
        $data = ... // load lesson from db
        return new Lesson($data, $this);
      }
    
      public getSeries($id) {
        if (isset($this->series[$id])) {
            return $this->series[$id];
        }
        $series = $this->loadSeries($id);
        $this->series[$id] = $series;
      }
    
      private loadSeries($id) {
        $data = ... // load series from db
        return new LessonSeries($data, $this);
      }
    }
    
    
    class Lesson {
      private $factory;
    
      public function __construct($data, LessonFactory $factory) {
         $this->factory = $factory;
    
         // + code to intialize object with $data
      }
    
      // this is how you get series from lessons
      public function getSeries() {
        return $this->factory->getSeries($this->seriesId);
      }
    }
    
    // somewhere in your page controller code
    $factory = new LessonsFactory();
    $lesson = $factory->getLesson($_GET['lessond_id']);