Большую часть времени, когда я пишу некоторый код, который обрабатывает ответ для определенного вызова функции, я получаю следующую структуру кода:
пример: это функция, которая будет обрабатывать аутентификацию для системы входа
class Authentication{
function login(){ //This function is called from my Controller
$result=$this->authenticate($username,$password);
if($result=='wrong password'){
//increase the login trials counter
//send mail to admin
//store visitor ip
}else if($result=='wrong username'){
//increase the login trials counter
//do other stuff
}else if($result=='login trials exceeded')
//do some stuff
}else if($result=='banned ip'){
//do some stuff
}else if...
function authenticate($username,$password){
//authenticate the user locally or remotely and return an error code in case a login in fails.
}
}
проблема
- Как вы можете видеть, код построен на
if/else
структуре, которая означает, что новый статус ошибки будет означать, что мне нужно добавитьelse if
утверждение, которое является нарушением принципа открытого закрытого доступа . - У меня возникает ощущение, что функция имеет разные уровни абстракции, поскольку я могу просто увеличить счетчик попыток входа в систему в одном обработчике, но делать более серьезные вещи в другом.
- Некоторые функции повторяются,
increase the login trials
например.
Я думал о преобразовании кратного if/else
в шаблон фабрики, но я использовал фабрику только для создания объектов, не меняющих поведения. У кого-нибудь есть лучшее решение для этого?
Замечания:
Это всего лишь пример использования системы входа в систему. Я прошу общее решение этого поведения, используя хорошо построенный шаблон OO. Этот тип if/else
обработчиков встречается в слишком многих местах в моем коде, и я просто использовал систему входа в систему как простой и понятный пример. Мои реальные варианты использования слишком сложны для публикации здесь. : D
Пожалуйста, не ограничивайте свой ответ PHP-кодом и не стесняйтесь использовать язык, который вы предпочитаете.
ОБНОВИТЬ
Еще один более сложный пример кода, чтобы прояснить мой вопрос:
public function refundAcceptedDisputes() {
$this->getRequestedEbayOrdersFromDB(); //get all disputes requested on ebay
foreach ($this->orders as $order) { /* $order is a Doctrine Entity */
try {
if ($this->isDisputeAccepted($order)) { //returns true if dispute was accepted
$order->setStatus('accepted');
$order->refund(); //refunds the order on ebay and internally in my system
$this->insertRecordInOrderHistoryTable($order,'refunded');
} else if ($this->isDisputeCancelled($order)) { //returns true if dispute was cancelled
$order->setStatus('cancelled');
$this->insertRecordInOrderHistory($order,'cancelled');
$order->rollBackRefund(); //cancels the refund on ebay and internally in my system
} else if ($this->isDisputeOlderThan7Days($order)) { //returns true if 7 days elapsed since the dispute was opened
$order->closeDispute(); //closes the dispute on ebay
$this->insertRecordInOrderHistoryTable($order,'refunded');
$order->refund(); //refunds the order on ebay and internally in my system
}
} catch (Exception $e) {
$order->setStatus('failed');
$order->setErrorMessage($e->getMessage());
$this->addLog();//log error
}
$order->setUpdatedAt(time());
$order->save();
}
}
Назначение функции:
- Я продаю игры на Ebay.
- Если клиент желает отменить свой заказ и получить свои деньги обратно (т.е. возмещение), я должен сначала открыть «Спор» на Ebay.
- После того, как спор открыт, я должен ждать, пока клиент подтвердит, что он согласен на возмещение (глупо, потому что он тот, кто сказал мне возместить, но это работает на ebay).
- Эта функция получает все открытые мной споры и периодически проверяет их статусы, чтобы узнать, ответил клиент на этот спор или нет.
- Клиент может согласиться (затем я верну деньги) или отказать (тогда я сделаю откат), или может не отвечать в течение 7 дней (я сам закрываю спор, а затем возвращаю деньги).
getOrderStrategy
это фабричный метод , который возвращаетstrategy
объект в зависимости от статуса заказа, но каковыpreProcess()
иpreProcess()
функции. И почему ты перешел$this
наupdateOrderHistory($this)
?