这几天公司里组织设计模式的学习,首先我非常赞同,这样的做法,我们公司不仅仅是创造价值的公司,更是培养人才的公司.记得之前我们经常说的世界上有三类公司,第一类是做标准的公司,第二类是做产品的公司,第三类是做外包的公司.我想说的是,我们不仅仅想要做标准,我们更重要的是培养人才!这也是我从日本公司经营理念感悟到的.好了,废话不多说了,这次设计模式,我有幸成为演讲者.团队给了我很大的帮助,在此再次谢谢我的团队和我的兄弟姐妹们.我们的头,每年让我们组织这种形式的学习,真是为了实践建构主义教学理念,孜孜不倦!很感谢我们的头,少了他世界就少了一个演奏建构主义的音旋的世界性大师!我认为人生的意义就在于此,当你离开人间迈进天堂的时候,请问百年之后,有谁还能说出你的事迹,这就是人生的长度和质量!忠于国家,忠于人民,让社会因有你而多了阳光和能量!自此,我的感受真的说完了!命令模式讲课正式开始!
讲课的重点就是这张图,首先我用一句话概括了命令模式的特点(Invoker)通过(Command)把行为抽象成一个个的对象,来实现请求者和执行者分离的目的。如何理解这句话,来看图:
之前的图是这样的:
这两张图的不同点就在:(Invoker)(Command)(ConcreteCommand)这三个类以及类的关系上。之前通过调研,我了解大家的关注点在:(Invoker)这里,其实命令模式的关键在于:(Command)
为什么这么说:
有了抽象命令,才有了封装行为的子类,(Invoker)的作用不小,但它发出的是命令,并不是执行者,真正的执行者还是(Receiver),这样是抽象命令把请求者和执行者分离开了。或者说是服务员的发出的命令实现了二者的分离!
这样的讲解,大家没有提出有价值的问题。不知道问题何在,然后我们就进行代码和图的对应的讲解,没想到问题出现在这里!下面是代码:
这是Clienk:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Command
{
class Program
{
static void Main(string[] args)
{
//实例化接收者和具体的命令
Receiver r = new Receiver();
Command a = new ConcreteCommandBakeMutton(r);
Command c = new ConcreteCommandBakeChickenWing(r);
Command b = new ConcreteCommandBakeChickenWing(r);
//实例化发出者
Invoker i = new Invoker();
//通过记录命令和执行命令来完成请求
i.SetCommand(c);
i.ExecuteCommand();
i.SetCommand(b);
i.ExecuteCommand();
i.SetCommand(a);
i.ExecuteCommand();
Console.Read();
}
}
}
这是Invoker类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Command
{
class Invoker
{
private Command command;
//接收记录菜单
public void SetCommand(Command command)
{
this.command = command;
}
//执行命令
public void ExecuteCommand()
{
command.Execute();
}
//这里可以通过取消命令的方法实现撤销类似的功能!
}
}
这是Command类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Command
{
//抽象的Command,用来让子类继承并实现里面具体的方法
abstract class Command
{
protected Receiver receiver;
public Command(Receiver receiver)
{
this.receiver = receiver;
}
//抽象的方法
abstract public void Execute();
}
}
ConcreteCommand类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Command
{
class ConcreteCommandBakeChickenWing :Command
{
//继承父类来实例化执行者类
public ConcreteCommandBakeChickenWing(Receiver receiver)
: base(receiver)
{ }
//执行者执行和此命令有关的方法,这样就实现了把行为封装成对象的作用
public override void Execute()
{
receiver.BakeChickenWing();
}
//同样可以封装多个方法,这样可以实现一组命令,实现宏命令!
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Command
{
//执行者类
class Receiver
{
//执行烤串的方法
public void BakeMutton()
{
Console.WriteLine("吃烤串!老子请!");
}
//执行烤鸡翅的方法
public void BakeChickenWing()
{
Console.WriteLine("吃烤鸡翅!老子请!");
}
}
}
讲课过程中,大家没有把图和代码对应上,我们以为能对应上,就直接演示了代码。这样一来,我们讲课出现了讨论,凡事有利有弊,通过讨论我们也明白了很多,发现了讲课还有很大的提升空间。在这里,希望读者好好运行一下代码,并与图对应上,因为你看到我的博客,就不是一名简简单单的码农,你将是什么,取决于你的行动。
我的重点还是这种图上,通过讲图就能发现命令模式的优势和不足,也能知道在什么情况下使用这个模式。
好处:通过把行为封装成对象,可以很容易的实现增加新的命令。
既然能把一个命令封装成对象,那么如果你把多个命令封装成对象,就实现了一组命令,也就是我们经常说的宏命令。
可以在同一时间多不同的行为,就是上面的延伸!
总是一句废话:解耦了,只有你明白为什么耦合这么强,如何解的藕,在什么条件下解耦,这句话才不是废话!
弊端:如果增加的新的命令很多,那么这就是它的不足。
在什么情况下用:就回到了上面怎样不把解耦变成废话的问题上了,小编自己总结的一句话,如果不合适大家积极拍板:一个类调用另一个类,或者多个类调用一个类的时候,调用的方法很多,容易变化,如果直接调用类的方法,这样两个类或者多个类耦合性很强,这种情况下就适合使用这种模式。当然,除了我说的,小编也总结了一下大家之言,分享一下,希望大家在读懂兵书的时候,不要被兵书所累。
命令模式的优点
降低系统的耦合度。
新的命令可以很容易地加入到系统中。
可以比较容易地设计一个命令队列和宏命令(组合命令)。
可以方便地实现对请求的Undo和Redo
命令模式的缺点
使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。
好了,知识性的讲解,就到这了,书不尽言,言不尽意。希望大家多多为他人提供帮助,这样你收获性更大,接下来,我想和大家再次聊聊建构主义教育。敬请期待!