想要确保我正确使用课程。主脚本从用户接受:
1. month
2. year
3. the type of event they want to find (microsoft or linux)
要找到微软事件的程序,必须运行正则表达式:'(ID =)+ [0-9] +' 要使程序找到linux事件,必须运行正则表达式:'(ID =)+ [A-F] +'
创建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;
}
}
我想在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;
}
}
答案 0 :(得分:4)
如果你想静态地使用所有东西(这使它基本上是一段漂亮的程序代码),你将不得不做这样的事情:
class Events
{
static protected $month;
static protected $year;
public static function microsoft_events($month, $year)
{
self::$month = $month;
self::$year = $year;
}
public static function linux_events($month, $year)
{
self::$month = $month;
self::$year = $year;
}
}
Events::microsoft_events(12, 2010);
请注意,您只能拥有一个实例,每次调用都会更改所有内容的值。
答案 1 :(得分:3)
$这不能在静态方法中使用 - 不能假设该类将在这里实例化...
您必须按照以下方式声明您的课程:
class Events
{
public static $month;
public static $year;
public function __construct(){ }
public static function microsoft_events($month, $year)
{
self::month = $month;
self::year = $year;
}
public static function linux_events($month, $year)
{
self::month = $month;
self::year = $year;
//do something?
if(self::month == 'March' && self::year == '2010'){
return 'Linux horoscope looks great';
}
return self::month . ' ' . self::year . ' is even better!';
}
}
通话:
$returnedVar = Events::linux_events('March', '2010');
答案 2 :(得分:3)
在我的头顶,我可以建议像
/// Raw event data, e.g. database
class EventStore {
function getRawDataMatching($pattern) {
// query the db
}
}
/// Mother of all Event types
abstract class Event {
static function getSearchPattern() {
// return the search pattern for the concrete event class
}
function __construct($rawData) {
// initialize from the raw data
}
}
/// Concrete event classes
class MicrosoftEvent extends Event {...}
class LinuxEvent extends Event {...}
/// Find events in the stream
class EventFinder
{
function __construct(EventStore $store) { ... }
function classFor($type) {
// return event class name for the given type
}
function find($date, $type) {
$klass = $this->classFor($type);
$pattern = $klass::getSearchPattern();
foreach($this->store->getRawDataMatching($pattern) as $data)
$result[] = new $klass($data)
}
}
// main code
$store = new EventStore($connectInfo);
$finder = new EventFinder($store);
$foundEvents = $finder->find($input->date, $input->type);
当然,这是许多可能的方式之一。如果您需要进一步的评论,请告诉我。
答案 3 :(得分:3)
我建议采用不同的方法。对每种偶数类型使用不同的方法将需要您编写重复代码,这最终将导致代价高昂的可维护代码并且容易出错(即使复制/粘贴也容易出错!我在一些项目中已经看到它以证明它)。 / p>
首先,当方法不要求在类成员中存储数据时,静态调用应该仅限制(或大部分);静态方法不应该设置任何东西,更少的数据由类本身的实例使用。因此,您应该使用单例模式。
其次,如果你应该有很多事件类型,每个事件都应该有适当的专业类。面向对象的设计从抽象到具体,从一般到专业。因此,您的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;
}
}
现在我们有了容器,我们需要事件类型,首先我们有基类:
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; }
}
然后,只需将它专门化(我们创建两个特殊事件类型):
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; }
}
添加新活动
Events::getInstance()
->addEvent( new LinuxEvent(2010, 7) )
->addEvent( new MicrosoftEvent(2008, 8) )
->addEvent( new MicrosoftEvent(2010, 2) )
->addEvent( new LinuxEvent(2009, 1) )
// ...
;
获取活动
// 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') );
正如您所看到的,类设计的开销稍微复杂一点,但之后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];
}
}
然后是我们的基本事件类型类
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);
}
}
现在,我们专注于类型
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; }
}
然后我们测试结果
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') );