想要确保我正确使用课程.主脚本从用户接受:
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)
我建议采用不同的方法。对每个偶数类型使用不同的方法将需要您编写重复的代码,这最终将导致昂贵的可维护代码并且容易出错(甚至复制/粘贴也容易出错!我在一些项目中看到了这一点来证明这一点)。
首先,只有(或大部分)当方法不需要在类成员中存储数据时,才应限制静态调用;静态方法不应该设置任何内容,类本身的实例使用的数据较少。因此,您应该使用单例模式。
其次,如果您应该有多种事件类型,则每种事件类型都应该有其适当的专门类。面向对象设计从抽象到具体,从通用到专业。因此,您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)
| 归档时间: |
|
| 查看次数: |
369 次 |
| 最近记录: |