设计模式学习笔记--Command命令模式
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
命令模式是对命令的封装。通过封装把发出命令的责任和执行命令的责任分割开,委派给不同的对象。命令(Command)模式属于对象的行为模式【GOF95】,它又称为行动(Action)模式或交易(Transaction)模式。
每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
命令模式涉及到五个角色,它们分别是:
1、客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。
2、命令(Command)角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色。
3、具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合;实现Exec ute()方法,负责调用接收考的相应操作。Execute()方法通常叫做执方法。
4、请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。
5、接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。
代码实现:
根据命令(Command)角色所要负责的工作,我们可分为两种方式来实现:
1、一种是Seperate方式,此方式下命令(Command)角色仅确定一个接收者和执行该请求的动作,因此,它需要在子类中完成具体的命令操作,并通过请求者(Invoker)角色这一中间层来与接收者互动。
2、另一种是Combine方式,此时命令(Command)角色要自己实现所有命令功能,根本不需要请求者(Invoker)角色,它自己充当了中间层来与接收者互动。
下面我们来用代码说明如何理解Command命令模式,程序如下图:
一、传统的做法:不采用Command模式的情况
1、定义一个类Car
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CommandCar
{
//一个类是一组操作和相应的一些变量的集合,现在有这样一个类Car,它有如下的一些操作
public class Car
{
public string curStateStr;
public Car()
{
curStateStr = "";
}
public void Start()
{
Console.WriteLine("车子起动");
}
public void MoveForwards()
{
Console.WriteLine("车子前进");
}
public void MoveBackwards()
{
Console.WriteLine("车子倒退");
}
public void Stop()
{
Console.WriteLine("车子停止");
}
}
}
2、使用这个类及其相关操作,写在Programme.cs中
#region通常的操作(紧耦合方式)
//通常的操作使得行为的请求者和行为的实现者之间呈现一种紧耦合,如果我
们要对相关操作进行Redo,Undo等操作则这种紧耦合方式就显得很复杂
//可以看到,客户程序是依赖于具体Car的命令(方法)的,引入Command 模式,需要对Car中的4个命令进行抽象
//在抽象前,在我们看来Start(),MoveForwards(),MoveBackwards(), Stop()这几个方法都应该是Car所具有的,
//如果单独抽象出来成一个命令对象,那就是把函数层面的功能提到了类的层面
Car mycar = new Car();
Console.WriteLine("--------常规方式执行效果如下----------"); mycar.Start();
mycar.MoveForwards();
mycar.MoveBackwards();
mycar.Stop();
// Console.ReadLine();
#endregion
这种情况下,把命令的接收者Car与行为(Start,Stop等操作)紧密耦合
二、Seperate方式
仍使用上面定义的类Car(它就是接收者Receiver角色),不同的是我们要加入以下角色
1、命令Command角色CarSeperateCommand
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CommandCar
{
//定义抽象类CarSeperateCommand,对于Function方式而言,它仅确定一个接收者Car和执行该请求的动作Excute。
//所以,在抽象类CarSeperateCommand中,只声明一个Excute的方法。这个方法在其子类(StartCommand类,MoveForwardsCommand类,MoveBackwardsCommand类,Sto pCommand类)中进行实现。
//(当然这个CarSeperateCommand还可以定义成接口)
//Car所具有的其他的具体命令类(StartCommand类,MoveForwardsCommand类,Mo veBackwardsCommand类,StopCommand类)都继承于该抽象类
//StartCommand类,MoveForwardsCommand类,MoveBackwardsCommand类,Sto pCommand类将用于封装对应的操作命令
public abstract class CarSeperateCommand
{
Car _car;
public CarSeperateCommand(Car mycar)