前进中的蜗牛

番茄大叔

水滴穿石,非一日之功;没有量变,何来质变。

命令模式

模式定义

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

UML类图

  • 抽象命令 Command 关联接收者,声明抽象命令函数。
  • 具体命令 ConcreteCommand 抽象命令类的子类,通过调用接收者对象方法实现了具体命令。
  • 调用者 Invoker 又称为请求者,它通过命令对象来执行请求。依赖命令对象。
  • 接收者 Receiver 执行与请求相关的子操作。

代码结构

public class CommandApp
	{
		public void Run()
		{
			Receiver receiver = new Receiver();
			Command command = new ConcreteCommand(receiver);
			Invoker invoker = new Invoker();

			invoker.SetCommand(command);
			invoker.ExecuteCommand();
			Console.ReadKey();
		}
	}

	/// <summary>
	/// 抽象命令
	/// </summary>
	abstract class Command
	{
		protected Receiver receiver;

		public Command(Receiver receiver)
		{
			this.receiver = receiver;
		}

		public abstract void Execute();
	}

	/// <summary>
	/// 具体命令
	/// </summary>
	class ConcreteCommand : Command
	{
		public ConcreteCommand(Receiver receiver) : base(receiver)
		{
		}

		public override void Execute()
		{
			receiver.Action();
		}
	}

	/// <summary>
	/// 接收者
	/// </summary>
	class Receiver
	{
		public void Action()
		{
			Console.WriteLine("Called Receiver.Action()");
		}
	}

	/// <summary>
	/// 调用者
	/// </summary>
	class Invoker
	{
		private Command _command;

		public void SetCommand(Command command)
		{
			this._command = command;
		}

		public void ExecuteCommand()
		{
			_command.Execute();
		}
	}

情景案例

电视机遥控器例子,电视器Receiver 遥控器Invoker。电视只有设置具体的台和声明,这里通过命名模式添加了在原来电视台和声音的加减。

public class User
	{
		public void Use()
		{
			TV tv = new TV();
			Command command = new ConcreteCommand(tv);
			RemoteControl remote = new RemoteControl();

			remote.SetCommand(command);

			remote.SetChannel(50);
			tv.Display();

			remote.DownChannel();
			remote.UpSound();
			tv.Display();

			Console.ReadKey();
		}
	}

	/// <summary>
	/// 抽象命令
	/// </summary>
	abstract class Command
	{
		protected TV tv;

		public Command(TV tv)
		{
			this.tv = tv;
		}
		/// <summary>
		/// 设置音量
		/// </summary>
		/// <param name="n"></param>
		public abstract void SetSound(int n);

		/// <summary>
		/// 设置频道
		/// </summary>
		/// <param name="n"></param>
		public abstract void SetChannel(int n);
	}

	/// <summary>
	/// 具体命令
	/// </summary>
	class ConcreteCommand : Command
	{
		public ConcreteCommand(TV tv) : base(tv)
		{
		}

		public override void SetChannel(int n)
		{
			this.tv.SetChannel(n);
		}

		public override void SetSound(int n)
		{
			this.tv.SetSound(n);
		}
	}

	/// <summary>
	/// 电视机
	/// </summary>
	class TV
	{
		private int _sound = 0;
		private int _channel = 0;

		public void SetSound(int n)
		{
			_sound = n;
		}

		public void SetChannel(int n)
		{
			_channel = n;
		}

		public void Display()
		{
			Console.WriteLine("现在电视的频道是:{0},音量是:{1}", _channel, _sound);
		}
	}

	/// <summary>
	/// 遥控器
	/// </summary>
	class RemoteControl
	{
		private int _sound=0;
		private int _channel=0;

		/// <summary>
		/// 最多有99个频道
		/// </summary>
		private int _maxChannel = 99;

		/// <summary>
		/// 音量最大100
		/// </summary>
		private int _maxSound = 100;

		private Command _command;

		public void SetCommand(Command command)
		{
			this._command = command;
		}

		/// <summary>
		/// 直接按数字输入频道
		/// </summary>
		/// <param name="n"></param>
		public void SetChannel(int n)
		{
			if (n >= 0 && n <= _maxChannel)
			{
				_channel = n;
				this._command.SetChannel(n);
			}
		}

		public void UpSound()
		{
			if(_sound < _maxSound)
			{
				_sound++;
			}
			this.SetSound(_sound);
		}

		public void DownSound()
		{
			if (_sound > 0)
			{
				_sound--;
			}
			this.SetSound(_sound);
		}

		public void UpChannel()
		{
			if (_channel < _maxChannel)
			{
				_channel++;
			}
			else
			{
				_channel = 0;
			}
			this.SetChannel(_channel);
		}

		public void DownChannel()
		{
			if (_channel > 0)
			{
				_channel--;
			}
			else
			{
				_channel = _maxChannel;
			}
			this.SetChannel(_channel);
		}

		private void SetSound(int n)
		{
			if(n>=0 && n<= _maxSound)
			{
				_sound = n;
				this._command.SetSound(_sound);
			}
		}
	}
posted @ 2018-02-02 18:33  LoveTomato  阅读(148)  评论(0编辑  收藏  举报