大话设计模式--第23章 烤羊肉串引来的思考——命令模式

来源:互联网 发布:java 自动生成实体类 编辑:程序博客网 时间:2024/04/29 23:07

23烤羊肉串引来的思考——命令模式

    以餐馆为例,若请求的实现者:厨师,既要去实现请求:去炒菜,又要对请求进行排队或纪录请求日志,以及支持可撤销的操作等,着显然会造成混乱,责任划分不明确。

    同样以餐馆为例,行为请求着:客户,显然不必要了解行为实现过程,甚至不需要知道行为实现者是谁,只需要与服务员打交道即可。让服务员负责纪录请求,进行请求的纪录、撤销等更加合适。

    还是以餐馆为例:我们可以把请求泛化处一个抽象类,让“服务员”直观对抽象的“命令”发号施令就可以了。具体事什么命令,有客户来决定就可以了。

    ¥:在命令(Command)模式中,对¥[命令]进行封装,命令中引用处理者,处理者具体负责处理请求。命令模式中还有¥[Invoker]角色负责管理¥[Command],负责Command的启动处理,删除请求,更新请求等。用户直接把请求交给Invoker角色即可。

    ¥:命令模式(Command),将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或则纪录请求日志,以及支持可撤销的操作。优点:

        第一,他能较容易地设计一个¥[命令队列]

        第二,在需要的情况下,可以较容易地将命令计入日志;

        第三,允许接受请求的一方决定¥[是否接受]请求,如,你到餐馆中订了一盘糖醋鱼,结果没有材料了,服务员就可以及时的提醒客户。

        第四,可以较容易地实现对请求的¥[撤销]和重做;

        第五,可以¥[加入]新的具体命令类而¥[不影响]其他的类。

        最后,命令模式可以把请求一个操作的对象与¥[知道]怎样执行一个操作的对象分割开,避免行为请求者行为实现者之间的¥[紧耦合]

    ¥:是否在碰到类似情况是一定要用命令模式?

        敏捷开发的原则告诉我们,不要为代码添加基于¥[猜测]的、实际¥[不需要]的功能。如果不清楚一个系统是否需要命令模式,一般就不要急着去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只是在真正需要如何撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。



    ¥:¥[barbecue] |ˈbɑːbɪkjuː|A.noun 户外烧烤、烤架、烧烤B.transitive verb 烧烤¥[bake] |beɪk| verb烘、烤/¥[mutton] |ˈmʌtn| noun羊肉/¥[wing] |wɪŋ| noun翅膀/¥[chicken] wing:鸡翅/¥[command] |kəˈmɑːnd, American -ˈmænd| noun命令/¥[execute] |ˈeksɪkjuːt| verb执行、实施、履行 execute command¥[notify] |ˈnəʊtɪfaɪ| verb通知 to notify [somebody] that ... 通知某人… notify somebody that execute command


abstract class Command

{

    protected Receiver receiver;

    public Command(Receiver receiver)

    {

        this.receiver = receiver;

    }

    abstract public void Execute();

}


class ConcreteCommand:Command

{

    public ConcreteCommand(Receiver receiver) : base(receiver)

    {

    }


    public override void Execute()

    {

        receiver.Action();

    }

}


class Invoker

{

    private Command command;

    public void SetCommand(Command command)

    {

        this.command = command;

    }

    public void ExecuteCommand()

    {

        command.Execute();

    }

}


class Receiver

{

    public void Action()

    {

        Console.WriteLine(“执行请求”);

    }

}


static void Main(string[] args)

{

    Receiver r =  new Receiver();

    Command c = new ConcreteCommand(r); //可以理解为准备菜单

    Invoker i = new Invoker();

    i.SetCommand(c);//可以理解为客户点菜

    i.ExecuteCommand();

    

    Console.Read();

}


23.3 紧耦合设计


//烤肉串者

public class Barbecuer

{

    //烤羊肉

    public void BakeMutton()

    {

        Console.WriteLine(“烤羊肉”);

    }

    //烤鸡翅

    public void BakeChickenWing()

    {

        Console.WriteLine(“烤鸡翅”);

    }

}


客户端调用

static void Main(string[] args)

{

    Barbecuer boy = new Barbecuer();

    boy. BakeMutton();

    boy. BakeMutton();

    boy. BakeMutton();

    boy. BakeChickenWing();

    boy. BakeMutton();

    boy. BakeMutton();

    boy. BakeChickenWing();


    Console.Read();

}



23.4 松耦合设计

//抽象命令

public abstract class Command

{

    protected Barbecuer receiver;


    // 抽象命令类,只需要确定‘烤肉串者’是谁

    public Command(Barbecuer receiver)

    {

        this. receiver= receiver;

    }

    //执行命令

    abstract public void ExcuteCommand();

}


//烤羊肉串命令类

class BakeMuttonCommand : Command

{

    public BakeMuttonCommand(Barbecuer receiver) :base(receiver){ }

    public override void ExcuteCommand()

    {

        receiver.BakeMutton();

    }

}


//烤鸡翅命令

class BakeChickenWingCommand : Command

{

    public BakeChickenWingCommand(Barbecuer receiver) :base(receiver){ }

    public override void ExcuteCommand()

    {

        receiver.BakeMutton();

    }

}



//服务员

public class Waiter

{

    private Command command;


    //设置订单,服务员类,不用管用户想要什么烤肉,反正都是‘命令’,只管记录订单,然后通知‘烤肉串者’执行即可。

    public void SetOrder(Command command)

    {

        this.command = command;

    }


    //通知执行

    public void Notify()

    {

        command. ExcuteCommand();

    }

}


static void Main(string[] args)

{

    //开店前的准备

    Barbecuer boy = new Barbecuer();

    Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);

    Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);

    Command bakeChickenWingComman1 = new BakeChickenWingCommand(boy);

    Waiter girl = new Waiter();

    //开门营业,来一个订单就通知一下是不合适的。

    girl.SetOrder(bakeMuttonCommand1);

    girl.Notify();

    girl.SetOrder(bakeMuttonCommand2);

    girl.Notify();

    girl.SetOrder(bakeChickenWingComman1);

    girl.Notify();


    Console.Read();

}


23.5 松耦合后

//服务员

public class Waiter

{

    private IList<Command> orders = new List<Command>();


    //设置订单

    public void SetOrder(Command command)

    {

        if (command.ToString() == “Command. BakeChickenWingCommand”)

        {

            Console.WriteLine(“没有鸡翅了”);

        }

        else

        {

            orders.Add(command);

            Console.WriteLine(“增加一个订单”);

        }

    }


    //取消订单

    public void CancelOrder(Command command)

    {

        orders.Remove(command);

        Console.WriteLine(“取消一个订单”);

    }


    //通知全部执行

    public void Notify()

    {

        foreach(Command cmd in orders)

        {

            cmd.ExcuteCommand();

        }

    }

}


static void Main(string[] args)

{

    //开店前的准备

    Barbecuer boy = new Barbecuer();

    Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);

    Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);

    Command bakeChickenWingComman1 = new BakeChickenWingCommand(boy);

    Waiter girl = new Waiter();

    //开门营业,来一个订单就通知一下是不合适的。

    girl.SetOrder(bakeMuttonCommand1);

    girl.SetOrder(bakeMuttonCommand2);

    girl.SetOrder(bakeChickenWingComman1);


    //点菜完毕,通知厨房

    girl.Notify();


    Console.Read();

}



23.6 命令模式

Receiver类

class Receiver

{

    public void Action()

    {

        Console.WriteLine(“执行请求!”);

    }

}



Command

abstract class Command

{

    protected Receiver receiver;

    public Command(Receiver receiver)

    {

        this. receiver = receiver;

    }

    abstract public void Execute();

}


class ConcreteCommand : Command

{

    public ConcreteCommand(Receiver receiver) : base(recover)

    {    }

    public override void Execute()

    {

        receiver.Action();

    }

}


Invoker

class Invoker

{

    private Command command;

    public void SetCommand(Command command)

    {

        this.command = command;

    }


    public void ExecuteCommand()

    {

        command.Execute();

    }

}


客户端代码

static void Main(string[] args)

{

    Receiver r = new Receiver();

    Command c = new ConcreteCommand(r);

    Invoker i = new Invoker();

    i. SetCommand(c);

    i. ExecuteCommand();


    Console.Read();

}

0 0