命令模式

上一篇 / 下一篇  2009-09-14 10:14:14 / 个人分类:.NET设计模式

我们以现实中的吃羊肉串为例,解释命令模式。假如我们要在客户端实现点2串羊肉串,1串鸡柳的行为,我们可以这么做:

首先,我们要有一个烧烤者的接口,它包含子类可以实现的方法,一个是烤羊肉,一个是烤鸡肉:

    Public interface Barbecue
    {
        void BarMutton();

        void BarChicken();
    }

然后我们定义两个烧烤者的具体类,他们都实现了烧烤接口的两个方法:

    class ConcreteBarbecue1 : Barbecue
    {
        public void BarMutton()
        {
            Console.WriteLine("ConcreteBarbecue1 is  BarMuttoning..");
        }

        public void BarChicken()
        {
            Console.WriteLine("ConcreteBarbecue1 is BarChicken..");
        }
    }

    class ConcreteBarbecue2 : Barbecue
    {
        public void BarMutton()
        {
            Console.WriteLine("ConcreteBarbecue2 is BarMuttoning..");
        }

        public void BarChicken()
        {
            Console.WriteLine("ConcreteBarbecue2 is BarChicken..");
        }
    }

在客户端我们可以这样写:

   //指定谁为我们烧烤
   ConcreteBarbecue1 barbecue = new ConcreteBarbecue1();
   //烧两串羊肉串
   barbecue.BarMutton();
   barbecue.BarMutton();
   //烧一个鸡柳
   barbecue.BarChicken();

可以看出,在这种实现方式中,命令的请求者(客户端)与命令的实现者(ConcreteBarbecue1类)之间紧耦合了,如果我们想撤销某个命令,或重做某个命令,或对命令进行记录,都是非常困难的。所以,我们必须将命令的实现者与命令的请求者进行解耦合。

我们看一下命令模式的定义:

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。[GOF《设计模式》]

所谓请求就是在我们调用的ConcreteBarbecue1类的那些方法,命令模式的关键就是将命令实现者的方法抽象成类,把函数层面的功能提升到类的层面,下面我们分别实现烤羊肉串类和烤鸡柳类:

    public abstract class BarCommand
    {
        protected Barbecue bar;

        public void Execute();
    }

    public class BarMutton:BarCommand
    {
        public BarMutton(Barbecue bar)
        {
            this.bar = bar;
        }

        public void Execute()
        {
            bar.BarMutton();
        }
    }

    public class BarChicken:BarCommand
    {
        public BarChicken(Barbecue bar)
        {
            this.bar = bar;
        }

        public void Execute()
        {
            bar.BarChicken();
        }
    }

 

我们拿BarChicken类说明一下,在构造一个BarChicken类实例的时候,传递给他一个烧烤者类的实例,然后调用BarChicken的Execute()方法的时候,其实就是调用了烧烤者实例的BarChicken()方法。

这就是我们所谓的将请求封装成对象。

然后,我们需要一个侍者类,来记录我们的命令:

    public class Waiter
    {
        List<BarCommand> barCommand;

        public Waiter()
        {
            barCommand = new List<BarCommand>();
        }

        public void SetOrder(BarCommand bar)
        {
            barCommand.Add(bar);
        }

        public void Action()
        {
            foreach (BarCommand bar in barCommand)
            {
                bar.Execute();
            }
        }
    }

我们只在waiter类里实现了添加命令和执行命令操作,其实还可以有插销、记录等方法。

然后客户端代码如下:

        static void Main(string[] args)
        {
            Waiter waiter = new Waiter();
            BarCommand command = new BarMutton(new ConcreteBarbecue1());
            waiter.SetOrder(command);
            waiter.SetOrder(command);
            command = new BarChicken(new ConcreteBarbecue1());
            waiter.SetOrder(command);
            waiter.Action();
        }


TAG:

 

评分:0

我来说两句

Open Toolbar