【问题标题】:Command Design Pattern - Execute method with return value命令设计模式 - 执行带有返回值的方法
【发布时间】:2020-07-05 08:48:08
【问题描述】:

我已经根据下面的 UML 实现了命令设计模式

Command 是一个名为 ICommand 的接口:

 public interface ICommand
    {
        CommandType CommandType { get; set; }
        Task  Execute();
    }

这是完美的设计,直到我被要求从 Task Execute(); 返回值以获取特定的具体命令,所以我想“好的,让我们添加一个新方法 Task<T> Execute<T>();”但这意味着我需要添加空实现所有实现ICommand接口的类(大约10个类)。

我希望 ConcreteCommand 只有一个 Execute 方法,这可能吗? 每个 ConcreteCommand 是否必须对其他方法有空实现? 有没有办法使用 Task 将这些方法组合成一个?

为了澄清起见,我希望有两种这样的方法:

 public interface ICommand
    {
        CommandType CommandType { get; set; }
        Task  Execute();
        Task<T> Execute<T>();
    }

谢谢!

【问题讨论】:

    标签: c# design-patterns


    【解决方案1】:

    由于调用者可以在运行时更改命令,因此必须有松散的类型安全性。对于知道命令返回值的情况,可以将其返回类型传递给 execute():

    using System;
    
    class Receiver {
        public bool someAction() {
            return false;
        }
        
        public string someAction2() {
            return "some action value";
        }
    
        public void voidAction() {
            Console.WriteLine("void action");
        }
    }
    
    interface ICommand {
        object doAction();
    };
    
    class ConcreteCommand : ICommand {
        private Receiver receiver;
        
        public ConcreteCommand(Receiver recv) {
            receiver = recv;
        }
        
        public object doAction() {
            return receiver.someAction();
        }
    }
    
    class ConcreteCommand2 : ICommand {
        private Receiver receiver;
        
        public ConcreteCommand2(Receiver recv) {
            receiver = recv;
        }
        
        public object doAction() {
            return receiver.someAction2();
        }
    }
    
    class VoidCommand : ICommand {
        private Receiver receiver;
        
        public VoidCommand(Receiver recv) {
            receiver = recv;
        }
        
        public object doAction() {
            receiver.voidAction();
            return true;
        }
    }
    
    class Invoker {
        private ICommand command;
        
        public void setCommand(ICommand cmd) {
            command = cmd;
        }
        
        public T execute<T>() {
            return (T) command.doAction();
        }
    }
    
    public class Program
    {
        public static void Main()
        {
            Invoker i = new Invoker();
            Receiver r = new Receiver();
            
            i.setCommand(new ConcreteCommand(r));
            Console.WriteLine(i.execute<bool>());
            
            i.setCommand(new ConcreteCommand2(r));
            Console.WriteLine(i.execute<string>());
            
            i.setCommand(new VoidCommand(r));
            i.execute<object>();
    
            ICommand[] commands = new ICommand[] {
                new ConcreteCommand(r),
                new ConcreteCommand(r),
                new ConcreteCommand2(r),
                new ConcreteCommand2(r),
                new VoidCommand(r)
            };
            
            foreach (ICommand c in commands) {
                i.setCommand(c);
                Console.WriteLine(i.execute<object>());
            }
        }
    }
    
    False
    some action value
    void action
    False
    False
    some action value
    some action value
    void action
    True
    

    【讨论】:

    • 感谢您的回答!仍然想知道没有返回值的具体命令怎么办? doAction 会是什么样子?
    • 由于doAction()返回一个对象,它必须返回一个值;对 void 命令使用虚拟值,例如 true。 (添加示例)
    猜你喜欢
    • 2019-07-19
    • 2020-06-11
    • 2016-04-12
    • 2011-02-15
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    相关资源
    最近更新 更多