大话设计模式的例子讲的非常的好,理解起来也方便!有时候忘了。想到这些特殊的例子感觉就是特别爽。
烤羊肉串带来的思考!
路边摊羊肉串:
老板,我这里排的比较先啊,我最先给钱。老板这个没有熟啊。我的是 辣的啊!老板没有放盐啊!场面混乱,已经分不清谁是谁的啊,人太多了。烤肉的质量也受到了影响,心情不好也就不好啊。烤肉的人心情受到了顾客的影响。
店面的烤肉
服务员,给我来两串羊肉串,2鸡翅,啤酒两瓶。
鸡翅没得啦,点别的吧,肉精吧。辣一点。
两者的比较啊:
路边的生意不稳定,往往就是那几个时间,客源不固定的,人多混乱,所以生意也是不稳定的。烤肉的时候谁都想最先吃到啊,烤肉老板一个人,所以忙的混乱啊。所有的人都没有事情,都盯着这里看,烤肉多那一串,考的好,大家都是比较的清楚的。
这里出现了什么关系了呢?
紧耦合
客户和肉串老板的紧耦合,所以容易出错和乱起来,也容易挑剔。这里就是行为的请求者和行为的实现者的紧耦合。我们需要记录哪几个人的羊肉串,有没有特殊的要求(辣不辣),付钱了没有,谁先谁后啊。这个都是请求做什么哦。对于请求的做出记录哦,也就是日志。
如果有人要求撤出请求不要了,或者有人要求重新烤过,这其实就是什么呢?
撤销和重做吧
所以啊,所有的请求排队或者记录日志,一节支持可以撤销的操作等行为时。行为的请求者和实现者之间的紧耦合是不是太合适的。
我们再说说烤肉店吧!
我们不认识烤肉的师傅,见都没有见到。我们只需要给接待的服务员说就好了。她给我们记录,然后将订单交给师傅去做。都有订单,必有先后顺序。不会乱,不会遗忘。
服务员,肉串太多了,给我少一串好?服务员在订单上画了一笔。搞定,然后通知师傅。让服务员解耦我们的客户与烤肉者之间的耦合这的不错哦
编程融入生活!
我们的抽象命令
//抽象命令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.BakeChickenWing();}}
我们烤肉的人在干啥呢?
//烤肉串者public class Barbecuer{public void BakeMutton(){Console.WriteLine("烤羊肉串!");}public void BakeChickenWing(){Console.WriteLine("烤鸡翅!");}}
还有个重要的人物就是我们的服务员啊,这个解耦的重要的工具。服务员下订单就是让我们的烤肉啊,还是其他的一些东西执行起来,最后的时候才可以去执行的。
//服务员public class Waiter{private Command command;//设置订单public void SetOrder(Command command){this.command = command;}//通知执行public void Notify(){command.ExcuteCommand();}}
最后看我们怎么去执行呢?
//开店前的准备Barbecuer boy = new Barbecuer(); 烤肉的人Command bakeMuttonCommand1 = new BakeMuttonCommand(boy); 创建一个烤那个啥的,谁去烤呢?就是烤肉的Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);Waiter girl = new Waiter();//开门营业girl.SetOrder(bakeMuttonCommand1);//下个订单,让我们的师傅去执行girl.Notify();girl.SetOrder(bakeMuttonCommand2);girl.Notify();girl.SetOrder(bakeChickenWingCommand1);girl.Notify();
这个程序肯定是还有问题的吧,真实的情况怎么可以这样的呢?每次只能点一个菜呢,通知一次。
第二嘛,我们不知道厨房的东西是否还有没得?我们应该检查一下涩,让我们的服务员
第三,我们的客户点了哪些菜我们是应该做记录的,以后好收费,还有可能客服中途取消之内的东西。
服务员,有个list的订单
public class Waiter{private IList<Command> orders = new List<Command>();//设置订单public void SetOrder(Command command){if (command.ToString() == "命令模式.BakeChickenWingCommand"){Console.WriteLine("服务员:鸡翅没有了,请点别的烧烤。");}else{orders.Add(command);Console.WriteLine("增加订单:" + command.ToString() + " 时间:" + DateTime.Now.ToString());}}//取消订单public void CancelOrder(Command command){orders.Remove(command);Console.WriteLine("取消订单:" + command.ToString() + " 时间:" + DateTime.Now.ToString());}//通知全部执行public void Notify(){foreach (Command cmd in orders){cmd.ExcuteCommand();}}}
执行的过程和我们的刚才是一样的哦,所以不要担心的。
命令模式:Command 将我们的一个请求封装成为一个对象,从而使你可用不同的请求对客服进行参数化,对请求排队或记录日志,以及支持可以撤销的操作。
我们看看我们的图片
Command命令设计模式中5个角色:
(1).客户角色:创建了一个具体命令对象并确定其接收者。
Barbecuer boy = new Barbecuer(); 烤肉的人
Command bakeMuttonCommand1 = new BakeMuttonCommand(boy); 命令,烤肉的人是接收者
(2).命令角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色,通常由一个java接口或java抽象类实现。
这个就是我们上面的Command,我们的服务员依赖于他。必须有命令服务员才去通知我们的厨房哦
(3).具体命令角色:定义一个接受者和行为之间的弱耦合;实现execute方法,负责调用接收者的相应操作。execute方法通常叫做 执行方法。
这里好理解吧,我们这个方法依赖于我们的具体的执行者,烤肉的人。烤肉的人里面的哪种方法呢?我们烤的是啥子?
(4).请求者(Invoke)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。
这个就是相当于我们的服务员哦,对吧!
(5).接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。
我们每一个命令的具体的执行者就是他,他就是烤肉的老板
命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。每一个命令都是一个操作,命令请求发出请求要求执行一个操作;命令接受方收到请求,并执行操作。命令模式允许命令请求方和命令接收方独立开来,使得命令请求方不必 知道命令接收方的接口,更不必知道请求是怎么被接收,以及操作是否被执行,何时被执行,以及是怎么被执行的。
服务员
//请求者角色
class Invoker{ private Command command; public Invoker(Command command){ this.command = command; } public void action(){ command.execute(); }
}
烤肉的
//接收者
class Receiver{
//行动方法 public void action(){ System.out.println("Action has been taken."); }
}
服务员依赖于Command ,Command 依赖于我们的接受者,烤肉的那个人。这样就间接的传达话语!
//抽象命令角色
interface Command{ void execute();
}
//具体命令类
class ConcreteCommand implements Command{ private Receiver receiver; public ConcreteCommand(Receiver receiver){ this.receiver = receiver; } public void execute(){ receiver.action(); }
}
客服端怎么样呢?
//客户端
public class Client{ public static void main(String[] args){ //客户端创建命令接受者Receiver receiver = new Receiver(); //客户端创建具体命令,并指定命令接受者Command command = new ConcreteCommand(receiver); //客户端创建请求者,并给请求者指定具体命令Invoker invoker = new Invoker(command); //命令请求者发出命令请求invoker.action(); }
}
Command命令设计模式的优缺点:
优点: 解耦了命令请求者和接受者之间联系。请求者调用一个命令,接受者接受请求并执行相应的动作,因为使用Command模式解耦,请求者无需知道接受者任何接口。
缺点: 造成出现过多的具体命令类。