设计模式系列漫谈之七 - 命令模式

小雪的故事暂停,欲知后事如何,请等下回再编!现在改编另一个故事。

故事
        小时候,我梦想自己成为一名真正的军人,对军营生活充满着向往.,军人的豪气,军人的英姿总给人无限遐想。闲暇之余,我喜欢看看军事题材的电视剧,包括《和平年代》、《历史的天空》、《沙场点兵》、《中国近卫军》、《垂直打击》、《石破天惊》、《铁色高原》。今年一部电视剧《士兵突击》再次让农村出身的傻根成为2007年最耀眼的明星。

          我想,大多数读过大学的人都经历过一段艰苦的军训生活(其实根本不算苦)。虽然这种军训每天也只是练练军姿,走走正步而已,但是还是觉得有点新鲜感。当时,在所有的教官中,我们的教官是最帅气的。大家还开玩笑说,他必将会成为我们学校所有女生的梦中情人。另外,他的嗓门特别大,立正! 稍息!向左转! 向右转!那声音简直是震耳欲聋!

          军人以服从命令为天职。立正! 稍息!向左转! 向右转!

命令模式(Command)的解决方案
         GOF在《设计模式》中对命令模式描述:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化。命令模式中需要定义的角色:命令接收者(Receiver)、命令抽象类(Command)、具体命令对象(LZCommand/SXCommand/XZZCommand/XYZCommand)、命令执行者(Invoker)。

命令接收者对象如下:

namespace XX
{
       
public class Receiver
      {
            
public Receiver()
            {
            }

            
public void LZ()
            {
                  
//立正;
            }
            
public void SX()
            {
                  
//稍息;
            }
            
public void XZZ()
            {
                  
//向左转;
            }
            
public void XYZ()
            {
                  
//向右转;
            }
      }
}

命令抽象类如下:

namespace XX
{
    
public abstract class Command
    {
         
protected Receiver _receiver=null;
         
public Command(Receiver receiver)
         {
               
this._receiver=receiver;
         }

         
public abstract void Execute();
    }
}

命令具体对象如下:

namespace XX
{
       
public class LZCommand:Command
       {
           
public LZCommand(Receiver receiver):base(receiver)
            {
            }

           
public override void Execute()
           {
               receiver.LZ();
           }
       }

       
public class SXCommand:Command
       {
           
public SXCommand(Receiver receiver):base(receiver)
            {
            }

           
public override void Execute()
           {
               receiver.SX();
           }
       }

       
public class XZZCommand:ICommand
       {
           
public XZZCommand(Receiver receiver):base(receiver)
            {
            }

           
public override void Execute()
           {
               receiver.XZZ();
           }
       }

       
public class XZZCommand:ICommand
       {
           
public XYZCommand(Receiver receiver):base(receiver)
            {
            }

           
public override void Execute()
           {
               receiver.XYZ();
           }
       }
}

命令执行者对象如下:

namespace XX
{
      
public class Invoker
      {
            
private ICommand _lz;
            
private ICommand _sx;
            
private ICommand _xzz;
            
private ICommand _xyz;

            
public Invoker(ICommand lz,ICommand sx,ICommand xzz,ICommand xyz)
            {
                  
this._lz=lz;
                  
this._sx=sx;
                  
this._xzz=zz;
                  
this._xyz=yz;    
              }

            
public void LZ()
            {
                  
this._lz.Execute();
            }
            
public void SX()
            {
                  
this._sx.Execute();
            }
            
public void XZZ()
            {
                  
this._xzz.Execute();
            }
            
public void XYZ()
            {
                  
this._xyz.Execute();
            }
      }
}


接下来,我们通过客户端进行调用。假如我们创建一个窗体,窗体上放置四个按钮,如下图:

调用代码如下:

public partial class Form1 : Form
{
         
private void Form1_Load(object sender, EventArgs e)
        {
               Receiver rec
=new Receiver();
               
               LZCommand lzCommand
=new LZCommand(rec);
               SXCommand sxCommand
=new SXCommand(rec);
               XZZCommand xzzCommand
=new XZZCommand(rec);
               XYZCommand xyzCommand
=new XYZCommand(rec);

               Invoker invoker
=new Invoker(lzCommand,sxCommand,xzzCommand,xyzCommand);
         }

        
private void btnLZ_Click(object sender, EventArgs e)
        {
               invoker.LZ();
         }

        
private void btnSX_Click(object sender, EventArgs e)
        {
               invoker.SX();
         }
        
private void btnXZZ_Click(object sender, EventArgs e)
        {
               invoker.XZZ();
         }
        
private void btnXYZ_Click(object sender, EventArgs e)
        {
               invoker.XYZ();
         }
}


最后一个问题,如果我要增加一个命令按钮“向后转”,怎么办呢?我们可以认为,向左转 + 向左转=向后转,所以实现如下:
invoker.XZZ();
invoker.XZZ();
当然这样的理解有些牵强。这里,我只想说明一个道理,那就是:封装的对象的颗粒度尽量最小化。

posted @ 2007-12-21 12:51  李华星  阅读(489)  评论(0编辑  收藏  举报