Состояние объекта в шаблоне проектирования метода Template - PullRequest
1 голос
/ 11 марта 2009

Вот пример реализации алгоритма в базовом классе абстрактов из http://sourcemaking.com/design_patterns/template_method/php

public final function showBookTitleInfo($book_in) {
    $title = $book_in->getTitle();
    $author = $book_in->getAuthor();
    $processedTitle = $this->processTitle($title);
    $processedAuthor = $this->processAuthor($author);
    if (NULL == $processedAuthor) {
        $processed_info = $processedTitle;
    } else {
        $processed_info = $processedTitle.' by '.$processedAuthor;
    }
    return $processed_info;
}

Мне это не нравится, потому что я думаю, что "showBookTitleInfo" слишком много знает о вызываемых им методах.

Вот еще один пример абстрактный класс template_method { var $ state; публичная функция __construct () { $ this-> state = 0; }

    public function processEvent( $event ) {
        $this->doFirstStep( $event );
        $this->doSecondStep( $event );
    }
    abstract public function doFirstStep( &$event );
    abstract public function doSecondStep( &$event );
}

class CustomLogic extends template_method {
    public function doFirstStep( &$event ) {
        echo __METHOD__.": state: ".$this->state." event: $event\n";
        $this->state++;
    }
    public function doSecondStep( &$event ) {
        echo __METHOD__.": state: ".$this->state." event: $event\n";
        $this->state++;
    }
}

почему мы передаем событие как побочную, если не меняем его значение? Как мне реализовать логику «мои шаги», если они используют текущее состояние, могут изменить его значение, а другие шаги могут прочитать измененное значение и тоже могут изменить его?

Например, я хочу внедрить механизм подсчета затрат для отправки сообщений по расписанию - простой и периодический (например: каждый понедельник, пятница до 23.05.2009).

Итак, я реализую алгоритм в абстрактном классе следующим образом:

abstract class AbstractCostCounter {
    public function countNotReccurentSendingCost($messageObj) {
        $totalMessages = $messageObj->getTotalMessages(); // multiple recipients are allowed
        $message_cost = 1; // just to give you an idea
        $this->cost = $totalMessages * $message_cost;
    }
    abstract public function countOptional();

    // I pass $messageObject not as by-reference, because it hasn't to be modified
    public function countCost( $messageObject ) {
        $this->countNotReccurentSendingCost( $messageObject );
        $this->countOptional( $messageObject );
    }

}

class TemplateNotReccurentCostCounting {
    public function countOptional($messageObj) {
        // do nothing
    }
}

class TemplateReccurentCostCounting {
    public function countOptional($messageObj) {
        $notReccurentSendingCost = $this->cost;
        $totalMessagesInScheduledPlan = $messageObj->getTotalMessagesInScheduledPlan();
        $reccurentSendingPlanCost = $notReccurentSendingCost * $totalMessagesInScheduledPlan;
        $this->cost = $reccurentSendingPlanCost;
    }
}

Я двигаюсь в правильном направлении? Это где шаблон шаблона проектирования шаблон должен быть реализован? Пожалуйста, дайте мне знать, если что-то не так с этим кодом.

P.S. Счетчик затрат не является производственным кодом. Я написал это, потому что хотел дать вам идею.

Спасибо, заранее

1 Ответ

1 голос
/ 11 марта 2009

Шаблон шаблонного метода дает родительскому классу большой контроль, родительский класс должен много знать об абстрактных методах (их сигнатурах), потому что он должен «контролировать» алгоритм. Кстати, конкретный метод в родительском классе должен быть окончательным.

У вас нет преимуществ с вашими методами firstStep secondStep, я могу реализовать то, что я хочу, в stepOne и ничего не делать в stepTwo ...

Вопрос в том, когда вы захотите использовать шаблонный шаблон, а не в том, как переписать его для большей гибкости:)

...