模板方法设计模式中的对象状态
这是来自 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 $状态; 公共函数 __construct() { $this->状态 = 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++;
}
}
我们将事件作为引用传递? 我应该如何实现“我的步骤”逻辑,如果它们正在使用当前状态,可以修改其值,并且其他步骤可以读取修改后的值并且也可以修改它?
例如,我想实现计划消息发送的成本计数机制 - 简单且重复(例如:每个星期一、星期五,直到 2009 年 5 月 23 日)。
因此,我在抽象类中实现该算法如下:
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;
}
}
我的方向正确吗? 这是模板方法设计模式应该实现的地方吗? 如果这段代码有问题,请告诉我。
PS 成本计数器不是生产代码。 我写它是因为我想给你一个想法。
提前致谢
Here is an implementation example of the algorigthm in the base absctract class from 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;
}
I don't like it becase I think, that "showBookTitleInfo" knows too much about the methods it calls.
Here is another example
abstract class template_method {
var $state;
public function __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++;
}
}
why we pass event as by-reference, if we don't change its value?
How should I implement "my steps" logic, if they are using current state, can modify its value, and other steps can read modified value and can modify it too?
For example, I want to implement cost counting mechanism for scheduled message sending - simple and reccurent(ex: every Mon, Fri until 23.05.2009).
So, I implement the algorithm in abstract class as following:
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;
}
}
Am I moving in the right direction?
Is it where Template method design pattern should be implemented?
Please let me know, if it is something wrong with this code.
P.S. cost counter is not a production code. I wrote it because I wanted to give you an idea.
Thanks, in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
模板方法模式给了父类很多控制权,父类必须了解很多关于抽象方法(它们的签名)的信息,因为它必须“控制”算法。 顺便说一句,父类中的具体方法必须是最终的。
你的firstStep SecondStep方法没有优势,我可以在stepOne中实现我想要的东西,而在stepTwo中什么都不做...
问题是你什么时候想使用模板方法模式,而不是如何重写它以提供更大的灵活性:)
The template method pattern gives the parent class a lot of control, the parent class has to know a lot about the abstract methods (their signature) because it has to 'control' the algorithm. BTW the concrete method in the parent class has to be final.
You have no advantage with your firstStep secondStep methods, I could implement what I want in stepOne and do nothing in stepTwo...
The question is when would you want to use Template Method Pattern, not how to rewrite it to give more flexibility :)