命令模式的疑惑:在命令模式的参与者中是不是应该删除TReceiver类? ( 积分: 100 )

  • 主题发起人 chinaplate
  • 开始时间
C

chinaplate

Unregistered / Unconfirmed
GUEST, unregistred user!
在刘艺的<设计模式>,命令模式一章中(P308),提到
命令对象的能力可大可小,在设计时有不同的选择。
A:一个极端是,它仅提供一个请求者和接受者之间的耦合,委托接收者执行请求者的命令;
B:另一个极端是,它自己实现所有功能,根本无须额外的接收者对象。
我可不可以这样理解?
在情况A时,命令对象TCommand功能弱化了,只是将请求者TInvoker的命令请求简单的交给了接收者TReceiver处理.
在情况B时,命令对象,准确的说是具体命令对象TConcreteCommand独立完成了该命令的所有操作,不需要有接收者参与。
我对命令模式的疑惑是,接收者TReceiver的命名和位置
我觉的TReceiver是TConcreteCommand完成特定功能时所需要的参与对象,它是TConcreteCommand的内部实现,按理它应该
封装在TConcreteCommand对象里面,外界(包括Client)不关心它,也不需要知道它的存在与实现形式。
我这么理解对吗?那么TReceiver就不应该作为独立的类成为命令模式的参与者。
从命名上讲,“接收者”的含义是什么呢?它在“接收”什么呢?
比如,在书的命令模式的带undo/redo的文本编辑器范例(P318)中,
具体命令对象TFontFormat是通过TFontDialog来产生新的TFont实例,我完全也可以不用TFontDialog,自己写一个类似的功能
来产生一个TFont实例。也就是说TReceiver类只是实现的细节而已.
 
在刘艺的<设计模式>,命令模式一章中(P308),提到
命令对象的能力可大可小,在设计时有不同的选择。
A:一个极端是,它仅提供一个请求者和接受者之间的耦合,委托接收者执行请求者的命令;
B:另一个极端是,它自己实现所有功能,根本无须额外的接收者对象。
我可不可以这样理解?
在情况A时,命令对象TCommand功能弱化了,只是将请求者TInvoker的命令请求简单的交给了接收者TReceiver处理.
在情况B时,命令对象,准确的说是具体命令对象TConcreteCommand独立完成了该命令的所有操作,不需要有接收者参与。
我对命令模式的疑惑是,接收者TReceiver的命名和位置
我觉的TReceiver是TConcreteCommand完成特定功能时所需要的参与对象,它是TConcreteCommand的内部实现,按理它应该
封装在TConcreteCommand对象里面,外界(包括Client)不关心它,也不需要知道它的存在与实现形式。
我这么理解对吗?那么TReceiver就不应该作为独立的类成为命令模式的参与者。
从命名上讲,“接收者”的含义是什么呢?它在“接收”什么呢?
比如,在书的命令模式的带undo/redo的文本编辑器范例(P318)中,
具体命令对象TFontFormat是通过TFontDialog来产生新的TFont实例,我完全也可以不用TFontDialog,自己写一个类似的功能
来产生一个TFont实例。也就是说TReceiver类只是实现的细节而已.
 
话说《三国演义》中,周瑜与孙权定下计谋,以孙权之妹为诱饵,骗刘备过江到东吴招亲,想趁机杀害刘备,索回荆州。诸葛亮早识破了诡计,令武将赵云随同并护卫刘备前往,并给赵云了三个锦囊,嘱咐他依次执行即可。结果,赵云按照诸葛亮的锦囊妙计行事,不仅帮助刘备将孙权之妹孙尚香夫人迎娶回来,还得到孙权之母吴国太的欢心,陪同刘备夫妇回了荆州。《三国演义》这段记叙,为后世创造了“锦囊妙计”和“赔了夫人又折兵”两个成语。
今天,我就“锦囊妙计”来说说Command模式。从面向对象的设计角度来说,锦囊妙计有以下几个特色:
1、妙计被装入锦囊后都变得一般模样,没有任何区别。
2、锦囊妙计自己是无法实施的,必须由某个人依计行事。
3、实施者有权利选择执行命令或不执行命令,也可以选择在什么时候执行。当然,在我们的故事中,赵云在合适的时间执行了合适的妙计,便为我们留下了精彩的故事。
这个故事用代码书写出来如下:
using System;
using System.Collections;
abstract class JinNang
{
public string message = &quot;&quot;;
public void Execute()
{
Console.WriteLine(message);
}
}
class JinNang1 : JinNang
{
public JinNang1()
{
this.message = &quot;ToDo:让刘备拜见岳艾乔国老,并大造声势。&quot;;
}
}
class JinNang2 : JinNang
{
public JinNang2()
{
this.message = &quot;ToDo:假报刘备:曹操起兵五十万,杀奔荆州。&quot;;
}
}
class JinNang3: JinNang
{
public JinNang3()
{
this.message = &quot;ToDo:向孙夫人揭穿了孙权和周瑜的阴谋,请求夫人保护。&quot;;
}
}
abstract class Receiver
{
protected Queue commands = new Queue();

public void SetCommand(JinNang c)
{
commands.Enqueue(c);
}
protected JinNang GetCommand()
{
if (this.commands.Count != 0)
{
JinNang c = (JinNang)this.commands.Dequeue();
return c;
}
else
return null;
}
public bool FulfilCommand(JinNang c)
{
if(c != null)
{
c.Execute();
return true;
}
else
{
Console.WriteLine(&quot;惨了!无计可施了!&quot;);
return false;
}
}
abstract public voiddo
ComplexJob();
}
class Zhaoyun : Receiver
{
public override voiddo
ComplexJob()
{
Console.WriteLine(&quot;护送刘备去东吴&quot;);
Console.WriteLine(&quot;到达市徐&quot;);
if(!FulfilCommand(GetCommand())) return;
Console.WriteLine(&quot;刘备娶了孙权之妹&quot;);
Console.WriteLine(&quot;发现刘备全不想回荆州&quot;);
if(!FulfilCommand(GetCommand())) return;
Console.WriteLine(&quot;被孙权追杀&quot;);
if(!FulfilCommand(GetCommand())) return;
Console.WriteLine(&quot;安然护送刘备抵达荆州,任务完成!&quot;);
}
}
class ZhuGeLiang
{
public void JinNangMiaoJi(Receiver r)
{
r.SetCommand(new JinNang1());
r.SetCommand(new JinNang2());
r.SetCommand(new JinNang3());
}
}
public class Client
{
public static void Main( string[] args )
{
Receiver r = new Zhaoyun();
ZhuGeLiang z = new ZhuGeLiang();

z.JinNangMiaoJi(r);
r.DoComplexJob();
}
}
“命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象”。通过将妙计封装成锦囊妙计,便成为可委派的妙计。由一个对象(ZhuGeLiang)创建并封装,然后传递给另一个对象(ZhaoYun),命令在此没有被立即执行,而是Enqueue了。当条件合适的时候,再将命令解开执行。另外,所有的锦囊妙计都有一个共同的特性,就是可以被执行。所以,赵云不用关心这个锦囊与那个锦囊有什么区别,只需执行便是了。
该例子仅仅取了一个Command模式的“意”,丢弃了Command模式的形。设计模式的应用无需过于死板。如果对Command模式感兴趣,可以访问《设计模式(18)-Command Pattern》
 
精彩之极,生动之极.(我看C#更明白一些:) 谢谢ugvanxk
也就是说,Receiver(赵云)是命令的具体执行者,当然也可以得到命令的具体返回结果.
还想请教ugvanxk,
如果按GOF的类图来看,ZhuGeLiang的角色是什么呢?
是不是我们抓住命令模式的核心就够了,而不必去理会某种教条的实现.
&quot;命令模式把发出命令的责任和执行命令的责任分割开&quot;
http://www.delphibbs.com/keylife/iblog_show.asp?xid=13760
 
接受答案了.
 
顶部