Обработка нескольких операций класса на фабрике - PullRequest
2 голосов
/ 11 февраля 2010

У меня есть следующий фабричный метод:

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 $errorNotifier;

}

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

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

По сути, $errorHandler - это класс, который при обнаружении ошибки PHP вызывает
$errorNotifier->throwException() функция.

Проблема в том, что после запуска функции и настройки класса у меня нет доступа к классу ErrorHandler, что означает, что я не могу его отключить / изменить свойства / методы доступа и т. Д.

Мне интересно, лучший ли способ сделать это - предоставить открытый метод доступа для захвата errorHandler, что-то вроде:

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

    return $this->handler;
}

Этот метод позволит Factory создавать новый экземпляр ErrorHandler и позволит внешнему коду получить доступ к ErrorHandler. Но затем я сталкиваюсь с проблемой, что если я хочу пойти и создать другой ErrorNotifier, первый перестанет работать, так как я переназначаю функцию обратного вызова для нового объекта. Похоже, что это будет крайне плохая практика, так как это будет неожиданное поведение.

У меня такое ощущение, что установка какого-либо "глобального" errorHandler заставила бы меня отключиться из-за этой же проблемы, так как во второй раз, когда я вызываю createErrorNotifier, первый не будет вызываться больше.

Может быть, решение может заключаться в том, чтобы вместо этого дать ErrorNotifier экземпляр ErrorHandler, и тогда ErrorNotifier может выступать в качестве прокси между клиентом и ErrorHandler? Что-то вроде:

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

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

Другой вариант может заключаться в том, чтобы полностью забыть об ErrorHandler и положиться на клиента, чтобы связать ErrorNotifier с каким-либо обработчиком (set_exception_handler(), ErrorhHandler и т. Д.).

Как бы вы справились с чем-то вроде этого? Я вовсе не против изменения дизайна классов.

Я очень настороженно отношусь к простому объединению двух классов, так как это фактически делает все это «не пригодным для повторного использования». Если я отделю функциональность errorHandler (вызывая функцию при возникновении ошибки) от функциональности errorNotifier (имея дело с ошибкой), тогда я смогу намного проще использовать их оба.

Ответы [ 2 ]

2 голосов
/ 15 февраля 2010

Вам, вероятно, лучше всего иметь прокси-класс или синглтон, который позволит вам получить доступ к обработчику ошибок, когда вам это нужно. Что-то вроде:

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;
    }
}

Это позволит вам всегда собирать один экземпляр ErrorHandler (через ErrorHandler :: getInstance ()), а также глобально изменять активный экземпляр всякий раз, когда вам нужно (через ErrorHandler :: setInstance ()).

0 голосов
/ 11 февраля 2010

Вы можете изменить createErrorNotifier (), чтобы он возвращал стандартный объект, содержащий как обработчик, так и уведомитель для данного экземпляра. Тогда вам не нужно беспокоиться о получателях и смешивать обработчик с более новым уведомителем. Например, попробуйте следующие изменения:

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,
    );

}

Затем, когда вы вызываете createErrorNotifier, вы можете получить доступ как к обработчику, так и к уведомителю для данного экземпляра:

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

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...