开发者

Handling Multiple Class Operations in a Factory

I have the following Factory Method:

public function createErrorNotifier($verbose_output = false, $logging = false)
{
    // First we get the handler
    $errorHandler = $this->buildErrorHandler();

    $errorNotifier = $this->buildErrorNotifier();

    // We attach the notifier to the handler
    $errorHandler->setCallback(array($errorNotifier, "throwExcepti开发者_运维百科on"));

    // Return the Notifier
    return $errorNotifier;

}

protected function buildErrorHandler()
{
    return new ErrorHandler(error_reporting());
}

protected function buildErrorNotifier()
{
    return new ErrorNotifier();
}

Basically, $errorHandler is a class that, when it detects a PHP error, calls the

$errorNotifier->throwException() function.

The problem is that after the function is ran, and the class is set up, I don't have access to the ErrorHandler class, which means I can't turn off it/change properties/access methods, etc.

I'm wondering if the best method to do this would be to provide for a public accessor method to grab the errorHandler, something like:

public function buildErrorHandler()
{
    if($this->handler == null)
    {
        $this->handler = new ErrorHandler();
    }

    return $this->handler;
}

This method would allow the Factory to create a new instance of ErrorHandler, and would allow outside code to get access to the ErrorHandler. But I then run into the problem that if I want to go and create another ErrorNotifier, the first one will stop working, as I am reassigning the callback to the new object. This seems like it would be extremely bad practice, as it would be unexpected behavior.

I have a feeling that setting any sort of 'global' errorHandler would cause me to trip over this same problem, as the second time I got to call createErrorNotifier, the first one will not be called anymore.

Maybe a solution might be to instead give ErrorNotifier an instance of ErrorHandler, and then the ErrorNotifier can act as a proxy between the client and the ErrorHandler? Something like:

class ErrorNotifier{
     public function __construct(ErrorHandler $handler)
     {
          $this->errorHandler = $handler;
          $this->setCallback(array($this, "throwException"));
     }

     public function setCallback($callback)
     {
          $this->errorHandler->setCallback($callback);
     }
}

Another option might be to completely forget about the ErrorHandler, and rely on the client to tie the ErrorNotifier to some sort of handler (set_exception_handler(), ErrorhHandler, etc).

How would you handle something like this? I'm not at all against changing the design of the classes.

I grow very wary of just merging the two classes, as it would basically render the entire thing 'not-as-reusable'. If I separate the errorHandler functionality (calling a function when an error occurs) from the errorNotifier functionality (dealing with the error), I can then much more easily reuse both of them.


You're probably best off having a proxy class or a singleton which would enable you to get at the error handler when you need it. Something like:

class ErrorHandler {
    private static $_instance = null;
    public static function getInstance()
    {
         if (null !== self::$_instance) {
              self::$_instance = new ErrorHandler;
         }
         return self::$_instance;
    }

    public static function setInstance(ErrorHandler $instance)
    {
         $oldInstance = self::$_instance;
         self::$_instance = $instance;
         return $oldInstance;
    }
}

This would allow you to always collect a single instance of ErrorHandler (via ErrorHandler::getInstance() ) and also globally change the active instance whenever you need to ( via ErrorHandler::setInstance() ).


You could change createErrorNotifier() to return a standard object containing both the handler and notifier for the given instance. Then you won't need to worry about getters and mixing up a handler with a newer notifier. For example, try the following changes:

public function createErrorNotifier($verbose_output = false, $logging = false)
{
    // First we get the handler
    $errorHandler = $this->buildErrorHandler();

    $errorNotifier = $this->buildErrorNotifier();

    // We attach the notifier to the handler
    $errorHandler->setCallback(array($errorNotifier, "throwException"));

    // Return the Notifier
    return (object)array(
        'notifier' => $errorNotifier,
        'handler' => $errorHandler,
    );

}

Then when you call createErrorNotifier, you could access both the handler and notifier for a given instance:

$not1 = $obj->createErrorNotifier(...);
var_dump($not1->notifier, $not1->handler);

I hope that this helps!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜