【发布时间】:2021-10-11 09:30:12
【问题描述】:
我正在尝试实现命令模式,所以它的工作方式如下:
- 有一个基类
Command<T>,所有其他命令都从该基类继承。 - 可以在派生自
Actor的类上执行命令。 - 每个接口都定义了
Actor可以执行的操作。例如。IMovable或ITurnable。 - 每个命令类都作用于特定的接口。例如。
Command<IMovable>。 - Actor 实现接口,这些接口定义了它们可以执行的操作。
这是我尝试实现它的方法:
// base interface for all action interfaces
public interface ICommandable { }
// interface for a move action
public interface IMovable : ICommandable
{
void Move();
}
// base actor class
public class Actor : ICommandable
{
public void ExecuteCommand(ICommand<ICommandable> command)
{
(command as Command<ICommandable>).Execute(this);
}
}
// an actor which can be moved
public class MovableActor: Actor, IMovable
{
public void Move()
{
Console.WriteLine("Move");
}
}
// an interface for commands
public interface ICommand<out T> { }
// base command class
public class Command<T> : ICommand<T> where T : ICommandable
{
public virtual void Execute(T robot) { }
}
// move command
public class MoveCommand : Command<IMovable>
{
public override void Execute(IMovable actor)
{
actor.Move();
}
}
这是我正在尝试做的一个例子:
MovableActor actor = new MovableActor();
Command<IMovable> cmd = new MoveCommand();
actor.ExecuteCommand(cmd);
我的实现的问题是ICommand 接口必须使用out 关键字作为其参数。我做了一些阅读,我明白为什么会这样,但我不知道如何实现我所描述的。我该如何实现?
如果这不可能,我应该如何更改我的描述,使其尽可能接近这个,但有效?
【问题讨论】:
-
我不明白你为什么需要
ICommand。如果我删除它,您的代码仍然可以正常编译。如果我删除out,它也可以正常编译 -
@canton7 代码编译得很好,但是当我尝试创建一个
MoveCommand并将其传递给MovableActor的ExecuteCommand()时,它不起作用。 -
如果您在问题中包含该代码会有所帮助
-
这里的基本问题是你的
MoveCommand.Execute必须被赋予IMovable——该方法取决于拥有IMovable。但是,您可以将任何内容传递给Actor.ExecuteCommand,甚至是诸如ICommand<ITurntable>之类的命令:没有什么可以阻止您这样做。但如果你这样做了,并用ICommand<ITurntable>调用MoveCommand.ExecuteCommand,MoveCommand.Execute会失败,因为它需要IMovable。 -
@canton7 谢谢,这正是我想要的。如果需要,请将其添加为答案,以便我接受。
标签: c# generics interface command-pattern