现代方式在php中声明一个类

JMC*_*JMC 5 php class

想要确保我正确使用课程.主脚本从用户接受:

1. month
2. year
3. the type of event they want to find (microsoft or linux)
Run Code Online (Sandbox Code Playgroud)

为了找到一个微软事件的程序,它必须运行正则表达式:'(ID =)+ [0-9] +'为了找到一个linux事件的程序,它必须运行正则表达式:'(ID =) + [AF] +"

创建Events类似乎是组织代码的合理方法.如果可能的话,我不想从主脚本中将所需的正则表达式发送到类中.我想告诉events类它是微软还是linux事件,让类根据每类事件类中预定义的变量返回处理过的数据.

我将现有代码编写为:

 class Events
    {
            var $month;
            var $year;
            var $event_identifier_expression;

      public function events($month, $year)
      {
       $this->month = $month;
       $this->year = $year;
       return $this->event_identifier_expression.$month.$year;
      }
    }
Run Code Online (Sandbox Code Playgroud)

我想在Events类中使用类似多个静态帮助器方法的东西.如果我将现有代码更改为下面的代码,它是否允许我独立于类外部调用microsoft_events和linux_events,这是创建类的正确方法吗?(感谢来自类外部调用静态函数的示例代码):

class Events
    {
            public function __construct()
            {var $month;
             var $year;
             var $event_identifier_expression;
            } 

      public static function microsoft_events($month, $year)
      {
       $this->month = $month;
       $this->year = $year;
       $this->event_identifier_expression = '(ID=)+[0-9]+';
       return $this->event_identifier_expression.$month.$year;
      }
      public static function linux_events($month, $year)
      {
       $this->month = $month;
       $this->year = $year;
       $this->event_identifier_expression = '(ID=)+[A-F]+';
       return $this->event_identifier_expression.$month.$year;
      }
    }
Run Code Online (Sandbox Code Playgroud)

Yan*_*hon 3

我建议采用不同的方法。对每个偶数类型使用不同的方法将需要您编写重复的代码,这最终将导致昂贵的可维护代码并且容易出错(甚至复制/粘贴也容易出错!我在一些项目中看到了这一点来证明这一点)。

首先,只有(或大部分)当方法不需要在类成员中存储数据时,才应限制静态调用;静态方法不应该设置任何内容,类本身的实例使用的数据较少。因此,您应该使用单例模式。

其次,如果您应该有多种事件类型,则每种事件类型都应该有其适当的专门类。面向对象设计从抽象到具体,从通用到专业。因此,您Events不应该知道它存储了多少个或什么事件,而应该将其留给调用者。这将使您拥有更加连贯的界面。

这是一个示例设计:

class Events {

   static private $_instance;

   static public function getInstance() {
      // lazy loading of the class instance will not use unnecessary resources
      if (null === self::$_instance) {
         self::$_instance = new self();  // <-- valid PHP declaration
      }
      return self::$_instance;
   }

   // class members

   protected $_events;      // protected allows inheritance, use private to forbid it

   // private constructor prohibit external instances to be created
   private function __construct() {
      $this->_events = array();
   }

   // (GETTER: methods that starts with 'get'...)
   // use $year before $month for priority order ($month is more precise than $year)
   public function getEvents($type, $year = null, $month = null) {
      $_values = array();

      // if we have any event of that type...
      if (array_key_exists($type, $this->_events)) {
         foreach ($this->_events[$type] as $event) {
            // filter events to return... (if $year is null, $month is ignored)
            if ((null === $year 
              || (($year == $event->getYear())
              && (null === $month || $month == $event->getMonth()) )) ) {

               $_values[] = $event;
            }
         }
      }

      return $_values;
   }

   // (SETTER: methods that starts with 'add', 'set', etc.)
   public function addEvent(AbstractEvent $event) {
      if (!array_key_exists($event->getType(), $this->_events)) {
         $this->_events[$event->getType()] = array();
      }
      $this->_events[$event->getType()][] = $event;

      // returning $this allows chaining. 
      // While some argue the design of this, I personally like it
      return $this;
   }

}
Run Code Online (Sandbox Code Playgroud)

现在我们有了容器,我们将需要事件类型,首先我们有我们的基类:

abstract class AbstractEvent {
   protected $_year;    // again, protected to enable inheritance
   protected $_month;

   public function __construct($year, $month) {
      // TODO : perform some argument check here
      $this->_year = $year;
      $this->_month = $month;
   }

   abstract public function getType();
   public function getYear() { return $this->_year; }
   public function getMonth() { return $this->_month; }
}
Run Code Online (Sandbox Code Playgroud)

然后,简单地对其进行专门化(我们创建两个专门化事件类型):

class MicrosoftEvent extends AbstractEvent {
   const TYPE = 'Microsoft';
   public function getType() { return self::TYPE; }
}

class LinuxEvent extends AbstractEvent {
   const TYPE = 'Linux';
   public function getType() { return self::TYPE; }
}
Run Code Online (Sandbox Code Playgroud)

添加新事件

Events::getInstance()
  ->addEvent( new LinuxEvent(2010, 7) )
  ->addEvent( new MicrosoftEvent(2008, 8) )
  ->addEvent( new MicrosoftEvent(2010, 2) )
  ->addEvent( new LinuxEvent(2009, 1) )
  // ...
;
Run Code Online (Sandbox Code Playgroud)

获取事件

// 1. get ALL Microsoft events
var_export( Events::getInstance()->getEvents(MicrosoftEvent::TYPE) );
// 2. get all events for 'Linux' in 2010
var_export( Events::getInstance()->getEvents('Linux', 2010) );
// 3. same as 1; $month will be ignored, because $year is not specified
var_export( Events::getInstance()->getEvents('Microsoft', null, 6) );
// 4. returns empty array because unknown event type
var_export( Events::getInstance()->getEvents('Foo') );
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,类设计的开销稍微复杂一些,但之后的 API 更加一致。一个好的设计必须应用可重用的模式,这就是在这里完成的。希望这可以帮助。

******编辑**** 由于您的问题已更改,这里是经过编辑的解决方案。它小得多,但仍然遵循相同的基本设计:

class Events {

   static private $_events = array();

   // GETTER
   static public function getEventType($type) {
      // if we have any event of that type...
      if (!array_key_exists($type, self::$_events)) {
         $eventClass = $type . 'Event';
         self::$_events[$type] = new $eventClass();
      }

      return self::$_events[$type];
   }

}
Run Code Online (Sandbox Code Playgroud)

然后我们的基本事件类型类

abstract class AbstractEvent {
   abstract public function getType();
   public function getIdentifier($year, $month) {
      return $this->getType().str_pad((int) $month, 2, '0', STR_PAD_LEFT).str_pad((int) $year, 4, '0', STR_PAD_LEFT);
   }
}
Run Code Online (Sandbox Code Playgroud)

现在,我们专门研究这些类型

class MicrosoftEvent extends AbstractEvent {
   const TYPE = 'Microsoft';
   public function getType() { return self::TYPE; }
}

class LinuxEvent extends AbstractEvent {
   const TYPE = 'Linux';
   public function getType() { return self::TYPE; }
}
Run Code Online (Sandbox Code Playgroud)

然后我们测试一下结果

var_export( Events::getEventType(MicrosoftEvent::TYPE)->getIdentifier(2008, 6) );
var_export( Events::getEventType(LinuxEvent::TYPE)->getIdentifier(2010, 2) );
var_export( Events::getEventType('Microsoft')->getIdentifier('2009', '08') );
Run Code Online (Sandbox Code Playgroud)